/**
 * @file    parallel_com.c
 * @brief   并机协议-串口(RS485)
 * @author  name
 * @version 1.0.1
 * @date    2023-04-24
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-24 <td>1.0.1     <td>Liuwei   <td>首次创建
 * <tr><td>2024-01-03 <td>1.0.2     <td>Liuwei   <td>解决非自动寻址，从机上报掉线故障问题
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "parallel_com.h"
#include "param_mng.h"
#include "cfg_prj.h"
#include "mcu_type.h"
#include "If_di.h"
#include "var_mng.h"
#include "diagnosis.h"
#include "base_math.h"
#include "parallel.h"
#include "If_rtc.h"
#include "sample.h"
#include "boot_param.h"
#include "event_mng.h"
#include "soc_calc.h"
#include "sop_calc.h"
#include "If_di.h"
#include "If_com.h"
#include "soh_calc.h"
#include "If_do.h"
#include "modbus_app.h"
#include "parallel.h"
#include "ctrl_mng.h"
#include "If_can.h"
#include "pcs_can_mng.h"
#include "pcs_rs485_mng.h"
#include "dev_afe.h"
/* macro/define --------------------------------------------------------------*/
#define RECV_REG_SIZE      (128)
/* typedef -------------------------------------------------------------------*/
typedef struct
{
    uint8_t addr;
    uint8_t cmd;
    uint16_t start_addr;
    uint16_t end_addr;
	uint16_t data_len;
    uint16_t recv_reg_buf[RECV_REG_SIZE];
}comm_data_type;

typedef struct 
{
    uint8_t cmd_id; 
    uint8_t (* cmd_deal_func)(const comm_data_type ,uint8_t * ,uint16_t *);
}cmd_func_type;

typedef struct 
{
    uint16_t addr;
	uint16_t par_id ;
	uint8_t par_len;
}para_map_type;

/**
 * @brief 并机运行状态  
 */
typedef enum
{
	PARALLEL_COM_INIT ,
	PARALLEL_COM_AUTO ,
	PARALLEL_COM_NORMAL ,
}parallel_run_type;

/* local functions -----------------------------------------------------------*/
static uint16_t crc_chk(uint8_t *data, uint16_t length);
static uint8_t check_frame_is_valid(uint8_t *rx_buf , uint16_t rx_len , comm_data_type *comm_data);
static uint8_t read_master_start_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t read_master_data_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t read_slave_data_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t ctrl_slave_reset(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t ctrl_slave_chg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t ctrl_slave_dsg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t ctrl_slave_all_chg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t ctrl_slave_all_dsg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t read_int_reg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
static uint8_t write_int_reg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len);
uint8_t parallel_bst_master_ask(uint8_t slave_addr , uint8_t *tx_buf ,uint16_t *send_len);

static uint8_t read_master_total_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static uint8_t read_bms_slave_base_msg(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len);  //主机读取从控
/** JBD内部协议 */

static void read_bms_base_msg(uint8_t *tx_buf , uint16_t *tx_len);  //读取单机数据
static void read_bms_prp_alm_param(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_prp_alm_sign_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_pack_param(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_pack_sign_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_calib_msg(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_calib_sign_param(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_module_msg(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_module_sign_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_sys_time(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_version(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_debug_msg(uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_dv(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_dp(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void read_bms_history(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_prp_alm_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_dp(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_dv(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_calib_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_calib_coeff(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_pack_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_sys_time(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_module_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);
static void write_bms_debug_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len);

static void com_master_auto_addr(uint8_t com_id , uint16_t cycle);
static void com_slave_auto_addr(uint8_t com_id , uint16_t cycle);
static void com_slave_send_reply(uint8_t com_id , uint8_t self_addr);
static void com_master_send_set_addr(uint8_t com_id , uint8_t set_addr);
static uint8_t com_slave_recv_master_set(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *reply_addr);
static uint8_t com_master_recv_slave_reply(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *reply_addr);

static uint16_t get_sys_mos_state(void);
static uint16_t get_sys_sign_msg(void);
static uint32_t pc_get_slave_prp(uint8_t addr);
static uint32_t pc_get_slave_alarm(uint8_t addr);
static uint16_t get_sys_salve_mos_state(uint8_t addr);
static uint16_t get_sys_slave_sign_msg(uint8_t addr);
/* static variables ----------------------------------------------------------*/
static uint8_t sleep_cmd[] = {0xFF,0x79,0x29,0x08,0x29,0x0A,0x00,0x06,0x11,0x4A,0x42,0x44,0xA5,0x02};
#define SLEEP_CMD_SIZE (sizeof(sleep_cmd)/sizeof(uint8_t)) 
static uint16_t m_open_reg_buf[4] = {0};
static uint8_t train_slave_idx = 0;   /* 轮询地址 */
static uint16_t train_cycle_cnt = 0;
static auto_addr_data_type com_auto_addr_data = {0};
static uint16_t master_check_cnt = 0;

extern uint8_t afe_deinit_flag;
//static uint16_t slave_check_cnt = 0;
//static uint8_t parallel_com_state = PARALLEL_COM_INIT;

/**
 * @brief 功能函数列表
 */
static cmd_func_type cmd_func_map_list[] = 
{
    {0x43 , read_master_start_msg } ,
    {0x44 , read_master_data_msg  } ,
    {0x45 , read_slave_data_msg   } ,  //并机数据
    {0x46 , ctrl_slave_reset      } ,          
    {0x47 , ctrl_slave_chg        } ,
    {0x48 , ctrl_slave_dsg        } ,
    {0x49 , ctrl_slave_all_chg    } ,
    {0x4A , ctrl_slave_all_dsg    } ,
	{0x50 , read_master_total_msg } ,  // 读取主机统计信息
    /* JBD 内部指令*/
    {0x78 , read_int_reg          } ,
    {0x79 , write_int_reg         } ,
};
#define CMD_MAP_LIST_NUM    CALC_ARRAY_SIZE(cmd_func_map_list)

static const uint16_t base_para_map_list[] = 
{
	PAR_ID_COV_ALM_VAL ,PAR_ID_COV_ALM_RCV, PAR_ID_COV_ALM_DLY ,
	PAR_ID_COV_PRP_VAL ,PAR_ID_COV_PRP_RCV, PAR_ID_COV_PRP_DLY ,  

	PAR_ID_CUV_ALM_VAL ,PAR_ID_CUV_ALM_RCV, PAR_ID_CUV_ALM_DLY , 
	PAR_ID_CUV_PRP_VAL ,PAR_ID_CUV_PRP_RCV, PAR_ID_CUV_PRP_DLY ,

	PAR_ID_BOV_ALM_VAL ,PAR_ID_BOV_ALM_RCV, PAR_ID_BOV_ALM_DLY ,
	PAR_ID_BOV_PRP_VAL ,PAR_ID_BOV_PRP_RCV, PAR_ID_BOV_PRP_DLY ,

	PAR_ID_BUV_ALM_VAL ,PAR_ID_BUV_ALM_RCV, PAR_ID_BUV_ALM_DLY ,
	PAR_ID_BUV_PRP_VAL ,PAR_ID_BUV_PRP_RCV, PAR_ID_BUV_PRP_DLY ,

	PAR_ID_OCC_ALM_VAL  ,PAR_ID_OCC_ALM_RCV  ,PAR_ID_OCC_ALM_DLY  ,
	PAR_ID_OCC_PRP_VAL  ,PAR_ID_OCC_PRP_DLY  ,PAR_ID_OCC_RCV_DLY  ,
	PAR_ID_OCC_LOCK_TIMES ,
	PAR_ID_OCC2_PRP_VAL ,PAR_ID_OCC2_PRP_DLY  ,PAR_ID_OCC2_RCV_DLY,
	
	PAR_ID_OCD1_ALM_VAL  ,PAR_ID_OCD1_ALM_RCV  ,PAR_ID_OCD1_ALM_DLY,
	PAR_ID_OCD1_PRP_VAL  ,PAR_ID_OCD1_PRP_DLY  ,PAR_ID_OCD1_RCV_DLY,
	PAR_ID_OCD1_LOCK_TIMES,
	PAR_ID_OCD2_PRP_VAL ,PAR_ID_OCD2_PRP_DLY,PAR_ID_OCD2_RCV_DLY  ,

	PAR_ID_OTC_ALM_VAL  ,PAR_ID_OTC_ALM_RCV  ,PAR_ID_OTC_ALM_DLY  ,
	PAR_ID_OTC_PRP_VAL  ,PAR_ID_OTC_PRP_RCV  ,PAR_ID_OTC_PRP_DLY  ,

	PAR_ID_UTC_ALM_VAL  ,PAR_ID_UTC_ALM_RCV  ,PAR_ID_UTC_ALM_DLY  ,
	PAR_ID_UTC_PRP_VAL  ,PAR_ID_UTC_PRP_RCV  ,PAR_ID_UTC_PRP_DLY  ,

	PAR_ID_OTD_ALM_VAL  ,PAR_ID_OTD_ALM_RCV  ,PAR_ID_OTD_ALM_DLY  ,
	PAR_ID_OTD_PRP_VAL  ,PAR_ID_OTD_PRP_RCV  ,PAR_ID_OTD_PRP_DLY  ,
	
	PAR_ID_UTD_ALM_VAL  ,PAR_ID_UTD_ALM_RCV  ,PAR_ID_UTD_ALM_DLY  ,
	PAR_ID_UTD_PRP_VAL  ,PAR_ID_UTD_PRP_RCV  ,PAR_ID_UTD_PRP_DLY  ,
	
	PAR_ID_OTM_ALM_VAL  ,PAR_ID_OTM_ALM_RCV  ,PAR_ID_OTM_ALM_DLY  ,
	PAR_ID_OTM_PRP_VAL  ,PAR_ID_OTM_PRP_RCV  ,PAR_ID_OTM_PRP_DLY  ,
	
	PAR_ID_OTE_ALM_VAL  ,PAR_ID_OTE_ALM_RCV  ,PAR_ID_OTE_ALM_DLY  ,
	PAR_ID_OTE_PRP_VAL  ,PAR_ID_OTE_PRP_RCV  ,PAR_ID_OTE_PRP_DLY  ,
	
	PAR_ID_UTE_ALM_VAL  ,PAR_ID_UTE_ALM_RCV  ,PAR_ID_UTE_ALM_DLY  ,
	PAR_ID_UTE_PRP_VAL  ,PAR_ID_UTE_PRP_RCV  ,PAR_ID_UTE_PRP_DLY  ,

	PAR_ID_TDIFF_ALM_VAL ,PAR_ID_TDIFF_ALM_RCV ,PAR_ID_TDIFF_ALM_DLY ,
	PAR_ID_TDIFF_PRP_VAL ,PAR_ID_TDIFF_PRP_RCV ,PAR_ID_TDIFF_PRP_DLY ,

	PAR_ID_VDIFF_ALM_VAL ,PAR_ID_VDIFF_ALM_RCV ,PAR_ID_VDIFF_ALM_DLY ,
	PAR_ID_VDIFF_PRP_VAL ,PAR_ID_VDIFF_PRP_RCV ,PAR_ID_VDIFF_PRP_DLY ,

	PAR_ID_SOCL_ALM_VAL  ,PAR_ID_SOCL_ALM_RCV  ,PAR_ID_SOCL_ALM_DLY  ,
	PAR_ID_SOCL_PRP_VAL  ,PAR_ID_SOCL_PRP_RCV  ,PAR_ID_SOCL_PRP_DLY  ,
};

#define BASE_PRP_PARA_NUM    (sizeof(base_para_map_list)/sizeof(base_para_map_list[0]))

static const para_map_type pack_para_map_list[] = 
{
	{0x00 ,PAR_ID_BATT_TYPE , 1  } ,  /*!<(000) */
	{0x01 ,PAR_ID_BATT_MFT  , 1  } ,  /*!<(001) */
	{0x02 ,PAR_ID_BLC_VOLT , 1  } ,   /*!<(002) */
	{0x03 ,PAR_ID_BLC_VDIFF , 1  } ,  /*!<(003) */
	{0x04 ,PAR_ID_HOT_START_TEMP , 1  } ,/*!<(004) */
	{0x05 ,PAR_ID_HOT_STOP_TEMP , 1  } , /*!<(005) */
	{0x06 ,PAR_ID_FULL_CHG_VOLT , 1  } , /*!<(006) */
	{0x07 ,PAR_ID_FULL_CHG_CURR , 1  } , /*!<(007) */
	{0x08 ,PAR_ID_BMS_CODE , 15  } ,   /*!<(008) */
	{0x17 ,PAR_ID_BMS_YEAR , 3  } ,    /*!<(009) */
	{0x1A ,PAR_ID_SN_CODE , 15  } ,    /*!<(012) */
	{0x29 ,PAR_ID_PACK_YEAR , 3  } ,   /*!<(013) */
	{0x2C ,PAR_ID_MFT_CODE , 15  } ,    /*!<(016) */
	{0x3B ,PAR_ID_PCS_CAN_TYPE , 1  } , /*!<(017) */
	{0x3C ,PAR_ID_IDE_SLP_VOLT , 1  } , /*!<(018) */
    {0x3D ,PAR_ID_IDE_SLP_DLY    , 1 } , /*!<(019) */
	{0x3E ,PAR_ID_BLC_MODE       , 1 } ,   /*!<020) */
	{0x3F ,PAR_ID_PCS_RS485_TYPE , 1 } ,   /*!<021) */
	{0x40 ,PAR_ID_CAN_RATE , 1 } ,       /*!<022) */
	{0x41 ,PAR_ID_RS485_RATE , 1 } ,   /*!<023) */
	{0x42 ,PAR_ID_IDE_SLP_CURR , 1 } ,   /*!<024) */
	{0x43 ,PAR_ID_IDE_SLEEP_DLY, 1 } ,   /*!<025) */
};

#define PACK_PARA_NUM    (sizeof(pack_para_map_list)/sizeof(para_map_type))
	
static const para_map_type calib_para_map_list[] = 
{
	{0x2000 , PAR_ID_STD_CAP     , 1  },
	{0x2002 , PAR_ID_FULL_CAP    , 1  },
	{0x2004 , VAR_ID_DISP_RCAP   , 1  },
	{0x2006 , VAR_ID_DISP_SOC    , 1  },
	{0x2008 , PAR_ID_SOH         , 1  },
	{0x200A , PAR_ID_CYCLE       , 1  }, 
	{0x200C , PAR_ID_DAMP_FACTOR , 1  }, 
	{0x200E , PAR_ID_CYCLE_COEFF , 1  }, 
	{0x2010 , PAR_ID_ACC_CHG_AH_H, 1  }, 
	{0x2012 , PAR_ID_ACC_CHG_AH_L, 1  },
	{0x2014 , PAR_ID_ACC_DSG_AH_H, 1  }, 
	{0x2016 , PAR_ID_ACC_DSG_AH_L, 1  }, 
	{0x2018 , PAR_ID_BATT_SELF_POW , 1  }, 
	{0x201A , PAR_ID_CB_L1_VOLT , 1  },
	{0x201C , PAR_ID_CB_L1_SOC , 1  }, 
	{0x201E , PAR_ID_CB_L2_VOLT , 1  }, 
	{0x2020 , PAR_ID_CB_L2_SOC , 1  }, 
	{0x2022 , PAR_ID_CB_H1_VOLT , 1  }, 
	{0x2024 , PAR_ID_CB_H1_SOC , 1  }, 
	{0x2026 , PAR_ID_CB_H2_VOLT , 1  }, 
	{0x2028 , PAR_ID_CB_H2_SOC , 1  }, 
	{0x202A , PAR_ID_SOP_CV , 1  },
	{0x202C , PAR_ID_SOP_CC , 1  }, 
	{0x202E , PAR_ID_SOP_DV , 1  }, 
	{0x2030 , PAR_ID_SOP_DC , 1  },
	{0x2032 , PAR_ID_CB_CELL_NUM , 1  },
};

#define CALIB_PARA_NUM    (sizeof(calib_para_map_list)/sizeof(para_map_type))
	
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
uint8_t parallel_com_recv_deal(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len , uint8_t addr_flag)
{
    uint16_t i = 0;
	uint16_t tx_idx = 0;
    uint8_t cmd_ok = FALSE;
    static comm_data_type bst_comm_data = {0};
    
    /** 广播休眠命令 */
    if((rx_len == SLEEP_CMD_SIZE) && (TRUE == math_cmp_str(sleep_cmd , rx_buf , rx_len)))
    {
        var_set_data(VAR_ID_CTRL_SLEEP , CMD_STANDBY_SLEEP);
        *tx_len = 0;
        return TRUE;
    }
    
    if(check_frame_is_valid(rx_buf ,rx_len , &bst_comm_data) != BST_CMD_TRUE)
        return FALSE;
    
    if(bst_comm_data.end_addr < bst_comm_data.start_addr)
        return FALSE;
    
	// 如果是0x50 不判断地址
	if(bst_comm_data.cmd == 0x50)
	{
		cmd_ok = read_master_total_msg(bst_comm_data , tx_buf , tx_len);
		if(TRUE == cmd_ok)
        {
            return TRUE;
        }
	}
	
	// 主机 实时数据，主机上报 
	if((PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR)) 
		&& (PARALLEL_MASTER_ADDR != bst_comm_data.addr)
		&& (bst_comm_data.start_addr == 0x1000))
	{
		if((bst_comm_data.addr != PARALLEL_MASTER_ADDR) && (bst_comm_data.addr > 0))
		{
			if(master_data_reg.com_err_state & (1 << (bst_comm_data.addr - 1)))
			{
				read_bms_slave_base_msg(bst_comm_data , &tx_buf[tx_idx] , tx_len);
				return TRUE;
			}
			else
				return FALSE;
		}
	}
	
	// addr_flag 为 1则需要判断地址，否则不判断地址
	if((addr_flag == 1) && (var_get_data(VAR_ID_SELF_ADDR) != bst_comm_data.addr) &&(BROADCASE_ADDR != bst_comm_data.addr))
		return FALSE;
	
    for( i = 0;i < CMD_MAP_LIST_NUM; ++ i)
    {
        if(bst_comm_data.cmd == cmd_func_map_list[i].cmd_id)
        {
            cmd_ok = cmd_func_map_list[i].cmd_deal_func(bst_comm_data , tx_buf , tx_len);
            if(TRUE == cmd_ok)
            {
				// 广播地址 主机回复，从机不回复
				if(BROADCASE_ADDR == bst_comm_data.addr)
				{
					if(PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR)) // 主机
						return TRUE;
					else
						return FALSE;
				}
				else
				{
					return TRUE;
				}
            }
            break;
        }
    }

    return FALSE;
}

uint8_t parallel_com_auto_addr(uint8_t com_id , uint16_t cycle)
{
	uint8_t rx_len = 0;
	uint8_t rx_buf[20] = {0};
	uint8_t set_addr = 0;
	if(RUN_STATE_AUTO_ADDR == com_auto_addr_data.run_state)
	{
		// 解决CAN上电 误报0问题
		parallel_master_update_self();	 
		parallel_master_calc();	
		if(ADDR_STATE_UNDEF == com_auto_addr_data.addr_state)
		{
			if(If_di_read_in(DI_ADDR_IN) == DI_IN_ON)
			{
				com_auto_addr_data.slave_chk_cnt += cycle;
				if(com_auto_addr_data.slave_chk_cnt >= COM_WAIT_DELAY/4)
				{
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_CMP;
					com_auto_addr_data.run_state = RUN_STATE_NORMAL;
					com_auto_addr_data.addr_state = ADDR_STATE_CFG;
					var_set_data(VAR_ID_SELF_ADDR , param_get_data(PAR_ID_SELF_ADDR));
					If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
				}
			}
			
			com_auto_addr_data.wait_dly_cnt += cycle;
			if(com_auto_addr_data.wait_dly_cnt >= COM_WAIT_DELAY)
			{
				com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
				com_auto_addr_data.run_state = RUN_STATE_AUTO_ADDR;
				com_auto_addr_data.addr_state = ADDR_STATE_CFG;
				com_auto_addr_data.wait_dly_cnt = 0;
				If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
				var_set_data(VAR_ID_SELF_ADDR , PARALLEL_MASTER_ADDR);
			}
		}
		else
		{
			if(PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR))
			{
				com_master_auto_addr(com_id , cycle);
			}
			else
			{
				com_slave_auto_addr(com_id , cycle);
			}
		}
		return TRUE;
	}
	else
	{
		if(PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR))
		{
			// 如果检测到地址脚为高，则进入从机等待状态
			if(If_di_read_in(DI_ADDR_IN) == DI_IN_ON)
			{
				master_check_cnt += cycle; 
				if(master_check_cnt >= 5000)
				{
					master_check_cnt = 0;
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
					com_auto_addr_data.run_state = RUN_STATE_AUTO_ADDR;
					com_auto_addr_data.addr_state = ADDR_STATE_CFG;
					var_set_data(VAR_ID_SELF_ADDR , 0x00);
				}
			}
			else
			{
				master_check_cnt = 0;
			}
			
			if(TRUE == If_com_recv_comp(com_id) && (If_di_read_in(DI_ADDR_IN) == DI_IN_ON))
			{
				rx_len = If_com_get_recv_num(com_id);
				if(rx_len >= 20)
					rx_len = 20;
          		If_com_get_recv_buf(com_id , rx_buf , rx_len);
				if(TRUE == com_slave_recv_master_set(rx_buf , rx_len , &set_addr))
				{
					if(set_addr == 0xff)
					{
						If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
						com_auto_addr_data.run_state = RUN_STATE_NORMAL;
						com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
					}
					else if(set_addr == 0x00)
					{
						com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
						com_auto_addr_data.run_state = RUN_STATE_AUTO_ADDR;
						com_auto_addr_data.addr_state = ADDR_STATE_CFG;
						var_set_data(VAR_ID_SELF_ADDR , 0x00);
					}
					else
					{
						;
					}
				}
			}
		}
		else
		{
			// 从机不主动变为主机,必须重启
			// if(If_di_read_in(DI_ADDR_IN) == DI_IN_OFF)
			// {
			// 	// 如果检测到地址脚为低，则进入主机状态
			// 	slave_check_cnt += cycle;
			// 	if(slave_check_cnt >= 5000)
			// 	{
			// 		slave_check_cnt = 0;
			// 		com_auto_addr_data.run_state = RUN_STATE_AUTO_ADDR;
			// 		com_auto_addr_data.addr_state = ADDR_STATE_UNDEF;
			// 	}	
			// }
			// else
			// {
			// 	slave_check_cnt = 0;
			// }
			
			if(TRUE == If_com_recv_comp(com_id))
			{
				rx_len = If_com_get_recv_num(com_id);
				if(rx_len >= 20)
					rx_len = 20;
          		If_com_get_recv_buf(com_id , rx_buf , rx_len);
				if(TRUE == com_slave_recv_master_set(rx_buf , rx_len , &set_addr))
				{
					if(set_addr == 0xff)
					{
						If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
						com_auto_addr_data.run_state = RUN_STATE_NORMAL;
						com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
					}
					else if(set_addr == 0x00)
					{
						com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
						com_auto_addr_data.run_state = RUN_STATE_AUTO_ADDR;
						com_auto_addr_data.addr_state = ADDR_STATE_CFG;
						var_set_data(VAR_ID_SELF_ADDR , 0x00);
					}
					else
					{
						;
					}
				}
			}
		}
		return FALSE;
	}
}

uint8_t parallel_com_master_deal(uint16_t cycle , uint8_t *tx_buf ,uint16_t *tx_len)
{
	static uint16_t times = 0;
	if(var_get_data(VAR_ID_SELF_ADDR) == PARALLEL_MASTER_ADDR)
	{
		train_cycle_cnt += cycle;
		if(train_cycle_cnt >= MASTER_TRAIN_CYCLE)
		{
			times ++ ;
			train_cycle_cnt = 0;
			/* 如果地址 0 , 则更新一次数据 */
			if((times % 2) || (0 == train_slave_idx)) // 每1S更新一次
			{
				// 更新主机自身数据
                parallel_master_update_self();	
				slave_ol_data[0].ol_state = 1;
				slave_ol_data[0].send_cnt = 1;
				slave_ol_data[0].recv_cnt = 0;
				// 计算统计数据 
				parallel_master_calc();	
				if(train_slave_idx == 0)
				{
					train_slave_idx = 1;
					slave_ol_data[train_slave_idx].send_cnt = 0;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				}
			}
			// 判断从机是否离线
			if(0 == slave_ol_data[train_slave_idx].recv_cnt)
			{
				if(slave_ol_data[train_slave_idx].send_cnt >= SLAVE_OL_OFF_TIMES)
				{
					slave_ol_data[train_slave_idx].send_cnt = 0;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				
					++ train_slave_idx;	
					if(train_slave_idx  >= CFG_PARALLEL_NUM - 1)
						train_slave_idx  = PARALLEL_MASTER_ADDR;
					
					slave_ol_data[train_slave_idx].send_cnt = 1;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				}
				else
				{
					++ slave_ol_data[train_slave_idx].send_cnt;
				}
			}
			else
			{
				slave_ol_data[train_slave_idx].send_cnt = 1;
				slave_ol_data[train_slave_idx].recv_cnt = 0;
				slave_ol_data[train_slave_idx].ol_state = 1;
				
				++ train_slave_idx;	
				if(train_slave_idx >= CFG_PARALLEL_NUM - 1)
					train_slave_idx = PARALLEL_MASTER_ADDR;
				
				slave_ol_data[train_slave_idx].send_cnt = 1;
				slave_ol_data[train_slave_idx].recv_cnt = 0;
				slave_ol_data[train_slave_idx].ol_state = 0;
			}
			
//			++ train_slave_idx;	
//			if(train_slave_idx  >= CFG_PARALLEL_NUM)
//				train_slave_idx  = 0;
				
//			slave_ol_data[train_slave_idx].send_cnt ++;
			// 非主机地址才发送 
			//if(train_slave_idx > 0)
			//{
				parallel_bst_master_ask(train_slave_idx + 1, tx_buf , tx_len);
				return TRUE;
		//	}
		//	else
		//		return FALSE;
		}
		else
		{
			return FALSE;
		}
	}
	
	return FALSE;
}

uint8_t parallel_com_slave_deal(uint16_t cycle , uint8_t *tx_buf ,uint16_t *tx_len)
{
	static uint16_t times = 0;
	if(var_get_data(VAR_ID_SELF_ADDR) == PARALLEL_MASTER_ADDR)
	{
		train_cycle_cnt += cycle;
		if(train_cycle_cnt >= MASTER_TRAIN_CYCLE)
		{
			times ++ ;
			train_cycle_cnt = 0;
			/* 如果地址 0 , 则更新一次数据 */
			if((times % 2) || (0 == train_slave_idx)) // 每1S更新一次
			{
				// 更新主机自身数据
                parallel_master_update_self();	
				slave_ol_data[0].ol_state = 1;
				slave_ol_data[0].send_cnt = 1;
				slave_ol_data[0].recv_cnt = 0;
				// 计算统计数据 
				parallel_master_calc();	
				if(train_slave_idx == 0)
				{
					train_slave_idx = 1;
					slave_ol_data[train_slave_idx].send_cnt = 0;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				}
			}
			// 判断从机是否离线
			if(0 == slave_ol_data[train_slave_idx].recv_cnt)
			{
				if(slave_ol_data[train_slave_idx].send_cnt >= SLAVE_OL_OFF_TIMES)
				{
					slave_ol_data[train_slave_idx].send_cnt = 0;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				
					++ train_slave_idx;	
					if(train_slave_idx  >= CFG_PARALLEL_NUM - 1)
						train_slave_idx  = PARALLEL_MASTER_ADDR;
					
					slave_ol_data[train_slave_idx].send_cnt = 1;
					slave_ol_data[train_slave_idx].recv_cnt = 0;
					slave_ol_data[train_slave_idx].ol_state = 0;
				}
				else
				{
					++ slave_ol_data[train_slave_idx].send_cnt;
				}
			}
			else
			{
				slave_ol_data[train_slave_idx].send_cnt = 1;
				slave_ol_data[train_slave_idx].recv_cnt = 0;
				slave_ol_data[train_slave_idx].ol_state = 1;
				
				++ train_slave_idx;	
				if(train_slave_idx >= CFG_PARALLEL_NUM - 1)
					train_slave_idx = PARALLEL_MASTER_ADDR;
				
				slave_ol_data[train_slave_idx].send_cnt = 1;
				slave_ol_data[train_slave_idx].recv_cnt = 0;
				slave_ol_data[train_slave_idx].ol_state = 0;
			}
			
//			++ train_slave_idx;	
//			if(train_slave_idx  >= CFG_PARALLEL_NUM)
//				train_slave_idx  = 0;
				
//			slave_ol_data[train_slave_idx].send_cnt ++;
			// 非主机地址才发送 
			//if(train_slave_idx > 0)
			//{
				parallel_bst_master_ask(train_slave_idx + 1, tx_buf , tx_len);
				return TRUE;
		//	}
		//	else
		//		return FALSE;
		}
		else
		{
			return FALSE;
		}
	}
	
	return FALSE;
}

uint8_t parallel_bst_master_ask(uint8_t slave_addr , uint8_t *tx_buf ,uint16_t *send_len)
{
    uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    tx_buf[tx_idx ++ ] = slave_addr;
    tx_buf[tx_idx ++ ] = 0x45;
    tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x54;
    tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;

    *send_len = tx_idx;
    
    return TRUE;
}

void parallel_com_master_broadcast_sleep(uint8_t com_id)
{
    If_com_send_str(com_id , sleep_cmd , SLEEP_CMD_SIZE);
}
/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  计算CRC校验码
 * @param  data
 * @param  length
 * @return uint8_t 
 */
static uint16_t crc_chk(uint8_t *data, uint16_t length)
{
    int j = 0;
    uint16_t reg_crc = 0xFFFF;
    while(length -- )
    {
        reg_crc ^= *data++;
        for(j= 0 ; j < 8 ; ++ j)
        {
          if(reg_crc & 0x01)  /* LSB(b0)=1*/
              reg_crc = (reg_crc>> 1) ^ 0xA001;
          else
              reg_crc = reg_crc >> 1;
        }
    }
    return reg_crc;
}

static uint8_t read_master_start_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t i = 0;
    uint16_t tx_idx = 0;
    uint16_t *p_data = m_open_reg_buf;
    uint16_t calc_crc = 0;
    
    if(var_get_data(VAR_ID_SELF_ADDR) != PARALLEL_MASTER_ADDR)
        return FALSE;

    if((comm_data.end_addr < comm_data.start_addr) && (comm_data.end_addr > M_REG_OPEN_END))
        return FALSE;

    m_open_reg_buf[0] = param_get_data(PAR_ID_CHG_VOLT);
    m_open_reg_buf[1] = SOFT_VER_MAIN * 100 + SOFT_VER_RELEASE;
    m_open_reg_buf[2] = 0x00;
    m_open_reg_buf[3] = 0x00;

    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;

    /* 获取数据 */
    for(i = comm_data.start_addr; i < comm_data.end_addr; i += 2)
    {
        tx_buf[tx_idx ++]  = p_data[i/2] >> 8;
        tx_buf[tx_idx ++]  = p_data[i/2] & 0xff;
    }

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;

    *tx_len = tx_idx;

    return TRUE;
}

static uint8_t read_master_data_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t i = 0;
	uint16_t j = 0;
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
    uint16_t data_len = 0;
    uint16_t *p_data = (uint16_t *)&tx_buf[8];
//    if(comm_data.end_addr > M_REG_DATA_END)
//        return FALSE;

    if(var_get_data(VAR_ID_SELF_ADDR) != PARALLEL_MASTER_ADDR)
        return FALSE;

    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0;
	tx_buf[tx_idx ++ ] = 0;
    
    p_data[data_len ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_CELL_NUM));
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.parallel_num);
	for( i = 0;i < 16; ++ i)
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_cell_buf[i]);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_max_volt);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_min_volt);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_batt_volt);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.total_bus_curr >> 16);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.total_bus_curr & 0xffff);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_max_temp);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_min_temp);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_soc);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_soh);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.avg_cycle);
	p_data[data_len ++] = LIT_TO_BIG(master_data_reg.com_err_state);
	p_data[data_len ++] = LIT_TO_BIG((master_data_reg.total_prp_msg.prp_word & 0xffff));

	for( i = 0;i < CFG_PARALLEL_NUM; ++ i)
	{
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].cell_num);
		for( j = 0;j < SLAVE_CELL_NUM; ++ j)
			p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].cell_volt_buf[i]);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].max_cell_volt);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].min_cell_volt);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].batt_volt);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].curr_h16);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].curr_l16);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].max_temp);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].min_temp);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].full_cap);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].real_cap);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].cycle);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].soc);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].soh);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].prp_volt_status.prp_msg);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].prp_temp_status.prp_msg);
		p_data[data_len ++] = LIT_TO_BIG(master_data_reg.slave_data[i].fet_status);
	}
    data_len *= 2;
    tx_idx += data_len;
    tx_buf[6] = data_len >> 8;
	tx_buf[7] = data_len & 0xff;
    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;

    *tx_len = tx_idx;

    return TRUE;
}

static uint8_t read_slave_data_msg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t i = 0;
    uint16_t tx_idx = 0;
    uint16_t *p_data = NULL;
    uint16_t calc_crc = 0;
    float ftemp = 0;
    int32_t s_curr;
	uint8_t temp_num = 0;
	uint8_t soh = 0;
	
    slave_data_type slave_data = {0};
 
	/** 接收到主机读区命令 */
	if(var_get_data(VAR_ID_SELF_ADDR) == comm_data.addr)
	{
		p_data = (uint16_t *)&slave_data;
		slave_data.cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
		if(slave_data.cell_num >= CELL_MAX_NUM)
			slave_data.cell_num = CELL_MAX_NUM; 
		for( i = 0;i < SLAVE_CELL_NUM; ++ i)
		{
			slave_data.cell_volt_buf[i] = var_get_data(VAR_ID_CELL_VOLT01 + i);
		}
		slave_data.max_cell_volt = var_get_data(VAR_ID_MAX_CELL_VOLT);
		slave_data.min_cell_volt = var_get_data(VAR_ID_MIN_CELL_VOLT);
		slave_data.batt_volt = var_get_data(VAR_ID_BATT_VOLT);
        ftemp = var_get_data(VAR_ID_BUS_CURR) * VAR_CURR_FACTOR - VAR_CURR_OFFSET;
        s_curr = ftemp * 100;
		slave_data.curr_h16 = s_curr >> 16;
        slave_data.curr_l16 = s_curr & 0xffff;
		ftemp = var_get_data(VAR_ID_MAX_TEMP_VAL) * 0.1 - 50;
		slave_data.max_temp = (int32_t)((ftemp + 273.15f) * 10);
		ftemp = var_get_data(VAR_ID_MIN_TEMP_VAL) * 0.1 - 50;
		slave_data.min_temp = (int32_t)((ftemp + 273.15f) * 10);
		slave_data.full_cap = param_get_data(PAR_ID_FULL_CAP);
		slave_data.real_cap = var_get_data(VAR_ID_DISP_RCAP);
		slave_data.cycle = param_get_data(PAR_ID_CYCLE);
		slave_data.soc = var_get_data(VAR_ID_DISP_SOC) * 0.01;
		soh = param_get_data(PAR_ID_SOH);
		if(soh > 100)
			soh = 100;		
		slave_data.soh = soh;
		slave_data.prp_volt_status.prp_msg = parallel_get_volt_prp_msg();
		slave_data.prp_temp_status.prp_msg = parallel_get_temp_prp_msg();
		slave_data.fet_status = parallel_get_fet_status();
		slave_data.alarm_status = parallel_get_alarm_status();
        for(i = 0;i < 15; ++ i)
        {
            slave_data.sn_code[i] = param_get_data(PAR_ID_SN_CODE + i);
        }
		slave_data.sop_cc = var_get_data(VAR_ID_SOP_CC);
		slave_data.sop_dc = var_get_data(VAR_ID_SOP_DC);
		slave_data.ver_test = SOFT_VER_TEST;
		slave_data.mos_temp = var_get_data(VAR_ID_MOS_TEMP) + 2231;
		slave_data.env_temp = var_get_data(VAR_ID_ENV_TEMP) + 2231; 
		slave_data.version = SOFT_VER_RELEASE;
		
		temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
		if(temp_num >= CFG_TEMP_NUM)
			temp_num = CFG_TEMP_NUM;
	
		slave_data.temp_num = temp_num;
		for( i = 0;i < SLAVE_TEMP_NUM; ++ i)
		{
			slave_data.cell_temp_buf[i] = var_get_data(VAR_ID_CELL_TEMP01 + i) + 2231;
		}
		
		tx_buf[tx_idx ++ ] = comm_data.addr;
		tx_buf[tx_idx ++ ] = comm_data.cmd;
		tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
		tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
		tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
		tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
        tx_buf[tx_idx ++ ] = 0x00;
		tx_buf[tx_idx ++ ] = S_SMP_DATA_SIZE * 2;
		/* 获取数据 */
		for(i = 0; i < S_SMP_DATA_SIZE; ++ i)
		{
			tx_buf[tx_idx ++]  = p_data[i] >> 8;
			tx_buf[tx_idx ++]  = p_data[i] & 0xff;
		}
        
		calc_crc = crc_chk(tx_buf , tx_idx);
		tx_buf[tx_idx ++] = calc_crc & 0xff;
		tx_buf[tx_idx ++] = calc_crc >> 8;

		*tx_len = tx_idx;
		
		 return TRUE;
	}
	else
	{
		return FALSE;
	}
}

static uint8_t ctrl_slave_reset(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    if(var_get_data(VAR_ID_SELF_ADDR) != comm_data.addr)
        return FALSE;

    var_set_data(VAR_ID_USE_CMD , VAR_USE_CMD_RESET);

    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x01;

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t ctrl_slave_chg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    if(var_get_data(VAR_ID_SELF_ADDR) != comm_data.addr)
        return FALSE;

    var_set_data(VAR_ID_USE_CMD , VAR_USE_CMD_CHG);
    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x01;

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t ctrl_slave_dsg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    if(var_get_data(VAR_ID_SELF_ADDR) != comm_data.addr)
        return FALSE;
        
    var_set_data(VAR_ID_USE_CMD , VAR_USE_CMD_DSG);

    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x01;

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t ctrl_slave_all_chg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    if(var_get_data(VAR_ID_SELF_ADDR) != PARALLEL_MASTER_ADDR)
        return FALSE;

    var_set_data(VAR_ID_USE_CMD , VAR_USE_CMD_ALL_CHG);
    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x01;
    
    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t ctrl_slave_all_dsg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	
    if(var_get_data(VAR_ID_SELF_ADDR) != PARALLEL_MASTER_ADDR)
        return FALSE;

    var_set_data(VAR_ID_USE_CMD , VAR_USE_CMD_ALL_DSG);
    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x01;
    
    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t read_int_reg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	uint16_t data_len = 0;
	
    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    /* 获取基本信息 */
    if(0x1000 == comm_data.start_addr)
	{
		read_bms_base_msg(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取保护参数 */
	else if((0x1800 == comm_data.start_addr) && (comm_data.end_addr == 0x1900))
	{
		read_bms_prp_alm_param(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取保护参数 */
	else if((0x1800 <= comm_data.start_addr) && (comm_data.start_addr < 0x1C00))
	{
		read_bms_prp_alm_sign_param(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取PACK参数 */
	else if((0x1C00 == comm_data.start_addr) && (comm_data.end_addr == 0x1CA0))
	{
		read_bms_pack_param(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取PACK参数 */
	else if((0x1C00 <= comm_data.start_addr) && (comm_data.start_addr < 0x2000))
	{
		read_bms_pack_sign_param(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取校准信息 */
	else if((0x2000 == comm_data.start_addr) && ((comm_data.end_addr <= 0x2050)))
	{
		read_bms_calib_msg(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取校准信息 */
	else if((0x2000 <= comm_data.start_addr) && ((comm_data.end_addr <= 0x2100)))
	{
		read_bms_calib_sign_param(comm_data ,&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取模块参数 */
	else if((0x2400 == comm_data.start_addr) && ((comm_data.end_addr == 0x2450)))
	{
		read_bms_module_msg(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取模块单个参数 */
	else if((0x2400 <= comm_data.start_addr) && ((comm_data.end_addr <= 0x2500)))
	{
		read_bms_module_sign_msg(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取时间 */
	else if(0x2800 == comm_data.start_addr)
	{
		read_bms_sys_time(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取版本信息 */
	else if(0x2810 == comm_data.start_addr)
	{
		read_bms_version(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取调试参数 */
	else if(0x2900 == comm_data.start_addr)
	{
		read_bms_debug_msg(&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取DV参数 */
	else if((comm_data.start_addr >= 0x3000) && (comm_data.end_addr <= 0x3400))
	{
		read_bms_dv(comm_data ,&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取DP参数 */
	else if((comm_data.start_addr >= 0x3800) && (comm_data.end_addr <= 0x3C00))
	{
		read_bms_dp(comm_data ,&tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取历史记录 */
	else if(0x4000 == comm_data.start_addr)
	{
		read_bms_history(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	else
	{
		;
	}

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}

static uint8_t write_int_reg(const comm_data_type comm_data , uint8_t *tx_buf ,uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	uint16_t data_len = 0;
	
    tx_buf[tx_idx ++ ] = comm_data.addr;
    tx_buf[tx_idx ++ ] = comm_data.cmd;
    tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
    tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
	/* 写入保护参数 */
	if((0x1800 <= comm_data.start_addr) && (comm_data.start_addr <= 0x1900))
	{
		write_bms_prp_alm_param(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 写入PACK参数 */
	else if((0x1C00 <= comm_data.start_addr) && (comm_data.start_addr <= 0x1D00))
	{
		write_bms_pack_param(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 写校准参数 */
	else if((0x2000 <= comm_data.start_addr) && (comm_data.start_addr < 0x2100))
	{
		write_bms_calib_param(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
    /* 写校准系数 */
	else if((0x2100 <= comm_data.start_addr) && (comm_data.start_addr < 0x2200))
	{
		write_bms_calib_coeff(comm_data , &tx_buf[8] , &data_len);
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 写模块参数 */
	else if((0x2400 <= comm_data.start_addr) && (comm_data.start_addr < 0x2500))
	{
	    write_bms_module_msg(comm_data , &tx_buf[8] , &data_len);	
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 设置时间 */
	else if(0x2800 == comm_data.start_addr)
	{
		write_bms_sys_time(comm_data , &tx_buf[8] , &data_len);	
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 设置调试参数 */
	else if((0x2900 <= comm_data.start_addr) && (comm_data.start_addr < 0x2980))
	{
	    write_bms_debug_msg(comm_data , &tx_buf[8] , &data_len);	
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取DV参数 */
	else if((comm_data.start_addr >= 0x3000) && (comm_data.start_addr <= 0x3400))
	{
		write_bms_dv(comm_data ,&tx_buf[8] , &data_len);		
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	/* 读取DP参数 */
	else if((comm_data.start_addr >= 0x3800) && (comm_data.start_addr <= 0x3C00))
	{
		write_bms_dp(comm_data ,&tx_buf[8] , &data_len);	
		tx_buf[tx_idx ++] = data_len >> 8;
		tx_buf[tx_idx ++] = data_len & 0xff;
		tx_idx += data_len;
	}
	else
	{
		;
	}

    calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}


static void read_bms_base_msg(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint32_t v32_data = 0;
	uint16_t idx_cnt = 0;
	uint8_t i = 0;
	uint8_t cell_num = 0;
	uint8_t temp_num = 0;
	uint8_t soh = 0;

	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_BATT_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_PACK_VOLT));
	v32_data = (sample_get_curr() + 3000)  * 100;
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_SOC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_RCAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_FULL_CAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_STD_CAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MOS_TEMP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_ENV_TEMP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_CURR_DR));
	soh = param_get_data(PAR_ID_SOH);
	if(soh > 100)
		soh = 100;
	p_buf[idx_cnt ++] = LIT_TO_BIG(soh);
	v32_data = diag_get_all_prp();
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	v32_data = diag_get_all_alarm();
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	p_buf[idx_cnt ++] = LIT_TO_BIG(get_sys_mos_state());
	p_buf[idx_cnt ++] = LIT_TO_BIG(get_sys_sign_msg());
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CYCLE));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MAX_CELL_SN));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MAX_CELL_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MIN_CELL_SN));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MIN_CELL_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_AGV_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MAX_TEMP_SN));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MAX_TEMP_VAL));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MIN_TEMP_SN));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MIN_TEMP_VAL));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_AGV_TEMP));
    if(var_get_data(VAR_ID_SELF_ADDR) == PARALLEL_MASTER_ADDR)
    {
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_CV));
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_CC));
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_DV));
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_DC));
    }
    else
    {
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_SOP_CV)); 
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_SOP_CC));
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_SOP_DV));
        p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_SOP_DC));
    }
	
	cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
	if(cell_num >= CELL_MAX_NUM)
		cell_num = CELL_MAX_NUM;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(cell_num);
	for(i = 0;i < cell_num; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_CELL_VOLT01 + i));
	}
	
	temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(temp_num);
	for(i = 0;i < temp_num; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_CELL_TEMP01 + i));
	}
	p_buf[idx_cnt ++] = 0;
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_BLC_NOW_IDX));
	p_buf[idx_cnt ++] = LIT_TO_BIG((SOFT_VER_MAIN << 8) + SOFT_VER_RELEASE);
	for( i = 0;i < 15; ++ i)
	{
		p_buf[idx_cnt ++] = param_get_data(PAR_ID_SN_CODE + i);
	}
	
	if(PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR))
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.parallel_num);
		p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.com_err_state);
	}
	else
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(1);
		p_buf[idx_cnt ++] = LIT_TO_BIG((1 << (var_get_data(VAR_ID_SELF_ADDR) - 1)));
	}
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(0);  // 新协议识别标志位 改为0x5AA5 为识别0地址
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_PCS_CAN_TYPE));  // 新协议识别标志位
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_PCS_RS485_TYPE));  // 新协议识别标志位
	
	*tx_len = idx_cnt * 2;
}

static uint8_t read_bms_slave_base_msg(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint32_t v32_data = 0;
	uint16_t idx_cnt = 0;
	uint8_t i = 0;
	uint8_t cell_num = 0;
	uint8_t temp_num = 0;
	uint8_t addr = 0;
	uint16_t std_cap = 0;
	uint8_t curr_dr = 0;
	uint8_t max_sn = 0;
	uint16_t max_val = 0;
	uint8_t min_sn = 0;
	uint16_t min_val = 0;
	uint16_t avg_val = 0;
	uint32_t sum_val = 0;
	uint16_t calc_crc = 0;
	uint16_t tx_idx = 0;
	int32_t curr = 0;

	addr = comm_data.addr - 1;
	
	if(addr >= CFG_PARALLEL_NUM)
		return FALSE;
	
	if((master_data_reg.com_err_state & (1 << addr)) == 0)
		return FALSE;
	
	tx_buf[tx_idx ++ ] = comm_data.addr;
	tx_buf[tx_idx ++ ] = comm_data.cmd;
	tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
	tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
	
	p_buf = (uint16_t *)&tx_buf[tx_idx + 2];  // 长度占用两个字节
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].batt_volt);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].batt_volt);
	curr = (master_data_reg.slave_data[addr].curr_h16 << 16) + master_data_reg.slave_data[addr].curr_l16;
	if(master_data_reg.slave_data[addr].curr_h16 & 0x8000)
		v32_data = 300000-(~curr + 1);
	else
		v32_data = curr + 300000; //20240811
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].soc * 100);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].real_cap);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].full_cap);
	if(master_data_reg.slave_data[addr].soh > 0)
		std_cap = master_data_reg.slave_data[addr].full_cap * 100 / master_data_reg.slave_data[addr].soh;
	else
		std_cap = master_data_reg.slave_data[addr].full_cap;
	p_buf[idx_cnt ++] = LIT_TO_BIG(std_cap);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].mos_temp - 2231);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].env_temp - 2231);
	
	if(master_data_reg.slave_data[addr].fet_status & (1 << 2))
		curr_dr = CURR_DR_DSG;
	else if(master_data_reg.slave_data[addr].fet_status & (1 << 3))
		curr_dr = CURR_DR_CHG;
	else
		curr_dr = CURR_DR_IDLE;
	
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(curr_dr);
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].soh);
	v32_data = pc_get_slave_prp(addr);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	v32_data = pc_get_slave_alarm(addr);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data >> 16);
	p_buf[idx_cnt ++] = LIT_TO_BIG(v32_data & 0xffff);
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(get_sys_salve_mos_state(addr));
	p_buf[idx_cnt ++] = LIT_TO_BIG(get_sys_slave_sign_msg(addr));
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].cycle);
	
	cell_num = master_data_reg.slave_data[addr].cell_num;
	if(cell_num >= CELL_MAX_NUM)
		cell_num = CELL_MAX_NUM;
	
	max_val = master_data_reg.slave_data[addr].cell_volt_buf[0];
	min_val = master_data_reg.slave_data[addr].cell_volt_buf[0];
	sum_val = master_data_reg.slave_data[addr].cell_volt_buf[0];
	max_sn = 1;
	min_sn = 1;
	for( i = 1;i < cell_num; ++ i)
	{
		sum_val += master_data_reg.slave_data[addr].cell_volt_buf[i];
		
		if(master_data_reg.slave_data[addr].cell_volt_buf[i] > max_val)
		{
			max_sn = i + 1;
			max_val = master_data_reg.slave_data[addr].cell_volt_buf[i];
		}
		
		if(master_data_reg.slave_data[addr].cell_volt_buf[i] < min_val)
		{
			min_sn = i + 1;
			min_val = master_data_reg.slave_data[addr].cell_volt_buf[i];
		}
	}
	avg_val = sum_val / cell_num;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(max_sn);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].max_cell_volt);
	p_buf[idx_cnt ++] = LIT_TO_BIG(min_sn);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].min_cell_volt);
	p_buf[idx_cnt ++] = LIT_TO_BIG(avg_val); // 平均电压
	
	max_val = master_data_reg.slave_data[addr].cell_temp_buf[0];
	min_val = master_data_reg.slave_data[addr].cell_temp_buf[0];
	sum_val = master_data_reg.slave_data[addr].cell_temp_buf[0];
	max_sn = 1;
	min_sn = 1;
	temp_num = master_data_reg.slave_data[addr].temp_num;
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;
	for( i = 1;i < temp_num; ++ i)
	{
		sum_val += master_data_reg.slave_data[addr].cell_temp_buf[i];
		// 无效值不参与计算
		if(master_data_reg.slave_data[addr].cell_temp_buf[i] == 2321)
			continue ;
		
		if(master_data_reg.slave_data[addr].cell_temp_buf[i] > max_val)
		{
			max_sn = i + 1;
			max_val = master_data_reg.slave_data[addr].cell_temp_buf[i];
		}
		
		if(master_data_reg.slave_data[addr].cell_temp_buf[i] < min_val)
		{
			min_sn = i + 1;
			min_val = master_data_reg.slave_data[addr].cell_temp_buf[i];
		}
	}
	avg_val = sum_val / temp_num;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(max_sn);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].max_temp - 2231);
	p_buf[idx_cnt ++] = LIT_TO_BIG(min_sn);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].min_temp - 2231);
	p_buf[idx_cnt ++] = LIT_TO_BIG(avg_val - 2231);
	
    p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_SOP_CV));
    p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].sop_cc);
    p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_DV));
    p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].sop_dc);
	
	cell_num = master_data_reg.slave_data[addr].cell_num;
	if(cell_num >= CELL_MAX_NUM)
		cell_num = CELL_MAX_NUM;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(cell_num);
	for(i = 0;i < cell_num; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].cell_volt_buf[i]);
	}
	
	temp_num = master_data_reg.slave_data[addr].temp_num;
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(temp_num);
	for(i = 0;i < temp_num; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].cell_temp_buf[i]-2231);
	}
	p_buf[idx_cnt ++] = 0;
	p_buf[idx_cnt ++] = LIT_TO_BIG(0);
	p_buf[idx_cnt ++] = LIT_TO_BIG(master_data_reg.slave_data[addr].version);
	for( i = 0;i < 15; ++ i)
	{
		p_buf[idx_cnt ++] = master_data_reg.slave_data[addr].sn_code[i];
	}
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(1);
	p_buf[idx_cnt ++] = LIT_TO_BIG(1 << addr);
	
	idx_cnt = idx_cnt * 2;
	
	tx_buf[tx_idx ++] = idx_cnt >> 8;
	tx_buf[tx_idx ++] = idx_cnt & 0xff;
	
	tx_idx = tx_idx + idx_cnt;
	
	calc_crc = crc_chk(tx_buf , tx_idx);
    tx_buf[tx_idx ++] = calc_crc & 0xff;
    tx_buf[tx_idx ++] = calc_crc >> 8;
	
	*tx_len = tx_idx;
	
    return TRUE;
}


void read_bms_prp_alm_param(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint16_t i = 0;
	
	for(i = 0;i < BASE_PRP_PARA_NUM; ++ i)
	{
        p_buf[idx_cnt ++ ] = LIT_TO_BIG(param_get_data(base_para_map_list[i]));
	}

	*tx_len = idx_cnt * 2;
}

void read_bms_prp_alm_sign_param(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint16_t i = 0;
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;

	start_addr = (comm_data.start_addr - 0x1800)/2;
	end_addr = (comm_data.end_addr - 0x1800)/2;

	for(i = start_addr;i < end_addr; ++ i)
    {
		if(i >= BASE_PRP_PARA_NUM)
			break;
			
		p_buf[idx_cnt ++ ] = LIT_TO_BIG(param_get_data(base_para_map_list[i]));
	}

	*tx_len = idx_cnt * 2;
}

static void read_bms_pack_param(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint16_t i = 0;
	uint16_t j = 0;
    uint8_t len = 0;
	
	for(i = 0;i < PACK_PARA_NUM; ++ i)
	{
        len = pack_para_map_list[i].par_len;
        /* 字符串存储模式是大端模式 不用翻转 */
        if((pack_para_map_list[i].par_id != PAR_ID_BMS_CODE) 
            &&(pack_para_map_list[i].par_id != PAR_ID_SN_CODE)
            &&(pack_para_map_list[i].par_id != PAR_ID_MFT_CODE))
        {
            for( j = 0;j < len; ++ j)
            {
                p_buf[idx_cnt ++ ] = LIT_TO_BIG(param_get_data(pack_para_map_list[i].par_id + j));
            }
        }
		else
        {
            for( j = 0;j < len; ++ j)
            {
                p_buf[idx_cnt ++ ] = param_get_data(pack_para_map_list[i].par_id + j);
            }
        }
	}

	*tx_len = idx_cnt * 2;
}

static void read_bms_pack_sign_param(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint16_t i = 0;
	uint16_t j = 0;
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t addr_num = 0;
	
	start_addr = (comm_data.start_addr - 0x1C00)/2;
	end_addr = (comm_data.end_addr - 0x1C00)/2;

	for(j = start_addr;j < end_addr; ++ j)
    {
		if(j >= BASE_PRP_PARA_NUM)
			break;
		
		addr_num = 0;
		for(i = 0;i < PACK_PARA_NUM; ++ i)
		{
			if((j >= addr_num) && (j < addr_num + pack_para_map_list[i].par_len))
			{
				if((pack_para_map_list[i].par_id != PAR_ID_BMS_CODE) 
					&&(pack_para_map_list[i].par_id != PAR_ID_SN_CODE)
					&&(pack_para_map_list[i].par_id != PAR_ID_MFT_CODE))
				{
					p_buf[idx_cnt ++ ] = LIT_TO_BIG(param_get_data(pack_para_map_list[i].par_id + (j - addr_num)));
					break;
				}
				else
				{
					p_buf[idx_cnt ++ ] = param_get_data(pack_para_map_list[i].par_id + + (j - addr_num));
					break;
				}
			}
			addr_num += pack_para_map_list[i].par_len;
		}	
	}

	*tx_len = idx_cnt * 2;
}

static void read_bms_calib_sign_param(const comm_data_type comm_data , uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint16_t i = 0;
	uint16_t j = 0;
	uint16_t read_len = 0;
	
	if(comm_data.end_addr <= comm_data.start_addr)
		return ;
	
	read_len = (comm_data.end_addr - comm_data.start_addr) / 2;
	for(i = 0;i < read_len; ++ i)
    {
		for( j = 0;j < CALIB_PARA_NUM; ++ j)
		{
			if(calib_para_map_list[j].addr == comm_data.start_addr + 2 * i)
			{
				if(VAR_ID_DISP_SOC == calib_para_map_list[j].par_id)
				{
					p_buf[idx_cnt ++ ] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_SOC));
				}
				else if(VAR_ID_DISP_RCAP == calib_para_map_list[j].par_id)
				{
					p_buf[idx_cnt ++ ] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_RCAP));
				}
				else
				{
					p_buf[idx_cnt ++ ] = LIT_TO_BIG(param_get_data(calib_para_map_list[j].par_id));
				}
				
				break;
			}
		}
		
		if(j == CALIB_PARA_NUM)
			p_buf[idx_cnt ++ ] = 0;
	}

	*tx_len = idx_cnt * 2;
}


static void read_bms_calib_msg(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t afe_sc_volt = 0;
	uint16_t afe_sc_dly = 0;
	uint8_t soh = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;

	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_STD_CAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_FULL_CAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_RCAP));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_DISP_SOC));
	soh = param_get_data(PAR_ID_SOH);
	if(soh > 100)
		soh = 100;
	p_buf[idx_cnt ++] = LIT_TO_BIG(soh);
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CYCLE));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_DAMP_FACTOR));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CYCLE_COEFF));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_ACC_CHG_AH_H));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_ACC_CHG_AH_L));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_ACC_DSG_AH_H));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_ACC_DSG_AH_L));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_BATT_SELF_POW));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_L1_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_L1_SOC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_L2_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_L2_SOC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_H1_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_H1_SOC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_H2_VOLT));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_H2_SOC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SOP_CV));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SOP_CC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SOP_DV));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SOP_DC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_CELL_NUM));
	p_buf[idx_cnt ++] = LIT_TO_BIG((uint16_t)(CURR_SMP_RES * 1000));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_CB_TEMP_NUM)); // 温度个数
	/*短路显示*/
	dev_afe_get_sc_curr_dly(&afe_sc_volt , &afe_sc_dly);
	p_buf[idx_cnt ++] = LIT_TO_BIG(afe_sc_volt); // 
	p_buf[idx_cnt ++] = LIT_TO_BIG(afe_sc_dly);
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SOC_CFG));
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_FUNC_CFG));
	
	*tx_len = idx_cnt * 2;
}

static void read_bms_module_sign_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	
	if(comm_data.start_addr == 0x2400)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_ADDR));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_ADDR + 1));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_ADDR + 2));
	}
	else if(comm_data.start_addr == 0x2406)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_MAC_ADDR));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_MAC_ADDR + 1));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_MAC_ADDR + 2));
	}
	else if(comm_data.start_addr == 0x2414)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_IP_PORT ));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_IP_PORT + 1));
	}
    else if(comm_data.start_addr == 0x2418)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SUB_CODE ));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SUB_CODE + 1));
	}
	else if(comm_data.start_addr == 0x241C)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_DNS_CODE ));
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_DNS_CODE + 1));
	}
	else if(comm_data.start_addr == 0x241E)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_REP_EN));
	}
	else if(comm_data.start_addr == 0x2420)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_CYCLE));
	}
	else
	{
		;
	}
		
	*tx_len = idx_cnt * 2;
	
}

static void read_bms_module_msg(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint8_t i = 0;
	
	for(i = 0;i < 3; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_ADDR + i));
	}
	for(i = 0;i < 3; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_MAC_ADDR + i));
	}
	for(i = 0;i < 2; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_IP_PORT + i));
	}
	for(i = 0;i < 2; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_SUB_CODE + i));
	}
	for(i = 0;i < 2; ++ i)
	{
		p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_DNS_CODE + i));
	}
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_CYCLE));
	
	p_buf[idx_cnt ++] = LIT_TO_BIG(param_get_data(PAR_ID_WIFI_REP_EN));

	*tx_len = idx_cnt;
}

static void read_bms_sys_time(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	rtc_data_type rtc_time = {0};
	
	If_rtc_read_time(&rtc_time);
    p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.year);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.month);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.day);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.hour);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.min);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.sec);

	*tx_len = idx_cnt * 2;
}

static void read_bms_version(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t i = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	uint8_t hard_name[16] = HARD_PLATFORM;
	uint8_t prj_name[16] = PRJ_NAME;
	
    p_buf[idx_cnt ++] = LIT_TO_BIG(boot_param_read_par(BP_ID_BOOT_VER));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_HARD_VER));
	p_buf[idx_cnt ++] = LIT_TO_BIG(SOFT_VER_MAIN);
	p_buf[idx_cnt ++] = LIT_TO_BIG(SOFT_VER_RELEASE);
	p_buf[idx_cnt ++] = LIT_TO_BIG(SOFT_VER_TEST);
	p_buf[idx_cnt ++] = LIT_TO_BIG(PROTOCOL_VER);
	for(i = 0;i < 8; ++ i)
	{
		p_buf[idx_cnt ++] = (hard_name[i * 2 + 1] << 8) + hard_name[i * 2];
	}
	
	for(i = 0;i < 8; ++ i)
	{
		p_buf[idx_cnt ++] = (prj_name[i * 2 +1] << 8) + prj_name[i * 2];
	}

	*tx_len = idx_cnt * 2;
}

static void read_bms_debug_msg(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;

    p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_TOOL_MODE));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MOS_CTRL));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_OUT_CTRL));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_MOS_CTRL));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_CTRL_BLC));
	p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_CTRL_SLEEP));
    p_buf[idx_cnt ++] = LIT_TO_BIG(var_get_data(VAR_ID_LED_SW));

	*tx_len = idx_cnt * 2;
}

static void read_bms_dv(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t i = 0;
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t tx_idx = 0;
	uint16_t v16_temp = 0;
	
	if((comm_data.start_addr < 0x3000) || (comm_data.start_addr > 0x3400)
		||(comm_data.end_addr < 0x3000) || (comm_data.end_addr > 0x3400))
		return ;
	
	start_addr = (comm_data.start_addr - 0x3000);
	end_addr = (comm_data.end_addr - 0x3000);
	for( i = start_addr;(i < end_addr) && (i < VAR_ID_MAX); ++ i)
	{
		v16_temp = var_get_data(i);
		tx_buf[tx_idx ++ ] = v16_temp >> 8;
		tx_buf[tx_idx ++ ] = v16_temp & 0x00ff;
	}
	
	*tx_len = tx_idx;
}

static void read_bms_dp(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t i = 0;
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t tx_idx = 0;
	uint16_t v16_temp = 0;
	
	if((comm_data.start_addr < 0x3800) || (comm_data.start_addr > 0x3C00)
		||(comm_data.end_addr < 0x3800) || (comm_data.end_addr > 0x3C00))
		return ;
	
	start_addr = (comm_data.start_addr - 0x3800);
	end_addr = (comm_data.end_addr - 0x3800);
	for( i = start_addr;(i < end_addr) && (i < VAR_ID_MAX); ++ i)
	{
		v16_temp = param_get_data(i);
		tx_buf[tx_idx ++ ] = v16_temp >> 8;
		tx_buf[tx_idx ++ ] = v16_temp & 0x00ff;
	}
	
	*tx_len = tx_idx;
}

static void read_bms_history(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx = 0;
    uint8_t *p_buf = tx_buf;
    uint16_t data_size = 0;
    uint8_t *p_data;
	uint16_t i = 0;
	static uint16_t event_num = 0; 
    static uint16_t event_send_cnt = 0;
    static uint16_t event_send_addr = 0;
    event_data_type event_msg = {0};
	uint8_t event_status = 0;
    idx = 0;

    switch(comm_data.recv_reg_buf[0])
    {
        case 0:
            event_send_cnt = 0;
            event_num = event_get_use_num();
            event_send_addr = event_get_index();
            /* 如果记录数为0，则返回无记录，如果记录为1，
                返回读取结束，如果记录大于1，则返回继续读取*/
            if(0 == event_num)
            {
                event_status = 0;
            }
            else if(1 == event_num)
            {
                event_status = 3;
            }
            else 
            {
                event_status = 1;
            }
            break;
        case 1:
            /* 如果记录数为最后条，则返回读取结束
               否则返回继续读取 */
            if(event_send_cnt + 1 == event_num)
            {
                event_status = 3;
            }
            else 
            {
                event_status = 1;
            }
            break;
        case 2:
            event_send_cnt -- ;
            ++ event_send_addr;

            event_status = 2;
            break;
        case 3:
            event_status = 3;
            break;
        default:
            break;
    }

    p_buf[idx ++ ] = event_status;

    if(0 != event_status)
    {
        event_read_event(event_send_addr , &event_msg);

        if(event_send_addr > 0)
           event_send_addr -- ;
        else
           event_send_addr = EVENT_MAX_SIZE - 1; 

        event_send_cnt ++;
    }
    else 
    {
        /* 无记录不读取发送 */
    }

    p_data = event_msg.byte_buf;
	data_size = sizeof(event_data_type);
    for( i = 0;i < data_size; ++ i)
    {
        p_buf[idx ++ ] = p_data[i];
    }
    
    *tx_len = idx;
}

static void write_bms_prp_alm_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t i = 0;
	const uint16_t *p_data = &comm_data.recv_reg_buf[2];
	start_addr = (comm_data.start_addr - 0x1800)/2;
	end_addr = (comm_data.end_addr - 0x1800)/2;
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		for(i = start_addr;i < end_addr; ++ i)
        {
			if(i >= BASE_PRP_PARA_NUM)
				break;

			param_set_data(base_para_map_list[i] , *p_data);
			++ p_data;
        }
	}
}

static void write_bms_pack_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
    uint16_t set_addr = 0;
	uint16_t i = 0 , j = 0;
    uint16_t k = 0;
	const uint16_t *p_data = &comm_data.recv_reg_buf[2];
    
	set_addr = (comm_data.start_addr - 0x1C00)/2;
    
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		for(k = 0;k < PACK_PARA_NUM ; ++ k)
		{
            if(set_addr == pack_para_map_list[k].addr)
            {
                if((pack_para_map_list[k].par_id != PAR_ID_BMS_CODE) 
                    &&(pack_para_map_list[k].par_id != PAR_ID_SN_CODE)
                    &&(pack_para_map_list[k].par_id != PAR_ID_MFT_CODE))
                {
                    for( j = 0; j < pack_para_map_list[k].par_len; ++ j)
                    {
                        param_set_data(pack_para_map_list[k].par_id + j , *p_data);
                        ++ p_data;
						// 修改CAN波特率
						if((pack_para_map_list[k].par_id + j) == PAR_ID_PCS_CAN_TYPE)
						{
							if(*p_data != PCS_CAN_MUST)
							{
								If_can_init(CAN_ID1 , 500000);
							}
							else
							{
								If_can_init(CAN_ID1 , 100000);
							}
						}
						// 修改RS485波特率
						if((pack_para_map_list[k].par_id + j) == PAR_ID_PCS_RS485_TYPE)
						{
							If_com_init_drv(COM_PCS , 9600);
						}
                    }
                }
                else
                {
                    for( j = 0; j < pack_para_map_list[k].par_len; ++ j)
                    {
                        param_set_data(pack_para_map_list[k].par_id + j , LIT_TO_BIG(*p_data));
                        ++ p_data;
                    }
                }

                i += pack_para_map_list[i].par_len;
                break;
            }
        }
	}
}

static void write_bms_dp(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t start_addr = 0;
	start_addr = (comm_data.start_addr - 0x3800);
    
	if(TOOL_MODE_DVDP != var_get_data(VAR_ID_TOOL_MODE))
        return ;
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		if(start_addr >= PAR_ID_BUF_SIZE)
			return ;

		param_set_data(start_addr , comm_data.recv_reg_buf[2]);
	}
    
}

static void write_bms_dv(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t start_addr = 0;
	start_addr = (comm_data.start_addr - 0x3000);

    if(TOOL_MODE_DVDP != var_get_data(VAR_ID_TOOL_MODE))
        return ;
    
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		if(start_addr >= VAR_ID_MAX)
			return ;
        
		var_set_data(start_addr , comm_data.recv_reg_buf[2]);
	}
}

static void write_bms_calib_param(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
    uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t i = 0;
	const uint16_t *p_data = &comm_data.recv_reg_buf[2];
	uint32_t set_val = 0;
	
	start_addr = (comm_data.start_addr - 0x2000)/2;
	end_addr = (comm_data.end_addr - 0x2000)/2;
	
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		for( i = start_addr; i < end_addr; i ++ )
		{
            set_val = *p_data ++;
			switch(i)
			{
				case 0x00:  //标称容量 -20241106 添加设置标称容量 同步修改满充容量和SOC 解决客户蓝牙设置不了满充容量，
                    param_set_data(PAR_ID_STD_CAP , set_val); 
					soh_set_full_cap(set_val);
					set_val = var_get_data(VAR_ID_DISP_RCAP) * 10000 / param_get_data(PAR_ID_FULL_CAP);
					soc_calc_set_soc(set_val);
					break;
				case 0x01:  //20241106 设置满充容量 同步修改SOC
					soh_set_full_cap(set_val);
					set_val = var_get_data(VAR_ID_DISP_RCAP) * 10000 / param_get_data(PAR_ID_FULL_CAP);
					soc_calc_set_soc(set_val);
					break;
				case 0x02:
				    if (set_val <= param_get_data(PAR_ID_FULL_CAP))
					{
						set_val = 10000 * set_val /param_get_data(PAR_ID_FULL_CAP);
						soc_calc_set_soc(set_val);
					}
					break;
				case 0x03:
					if(set_val <= 10000)
					{
						soc_calc_set_soc(set_val);
					}
					break;
				case 0x04:
					soh_set_val(set_val);
					break;
				case 0x05:
					if (set_val <= SOH_CYCLE_MAX)
					{
						soh_set_cycle(set_val);
                    	soc_set_cycle(set_val);
					}
					break;
				case 0x06:
					param_set_data(PAR_ID_DAMP_FACTOR , set_val);
					break;
				case 0x07:
					param_set_data(PAR_ID_CYCLE_COEFF , set_val);
					break;
				case 0x08:
                    set_val = (set_val << 16) + (*p_data ++);
                    soc_set_acc_chg(set_val);
                    ++ i;
					break;
                case 0x0A:
                    set_val = (set_val << 16) + (*p_data ++);
                    soc_set_acc_dsg(set_val);
                    ++ i;
					break;
                case 0x0C:
					param_set_data(PAR_ID_BATT_SELF_POW , set_val);
					break;
				case 0x0D:
					param_set_data(PAR_ID_CB_L1_VOLT , set_val);
					break;
                case 0x0E:
					param_set_data(PAR_ID_CB_L1_SOC , set_val);
					break;
                case 0x0F:
					param_set_data(PAR_ID_CB_L2_VOLT , set_val);
					break;
                case 0x10:
					param_set_data(PAR_ID_CB_L2_SOC , set_val);
					break;
                case 0x11:
					param_set_data(PAR_ID_CB_H1_VOLT , set_val);
					break;
                case 0x12:
					param_set_data(PAR_ID_CB_H1_SOC , set_val);
					break;
                case 0x13:
					param_set_data(PAR_ID_CB_H2_VOLT , set_val);
					break;
                case 0x14:
					param_set_data(PAR_ID_CB_H2_SOC , set_val);
					break;
				case 0x15:
					param_set_data(PAR_ID_SOP_CV , set_val);
					break;
				case 0x16:
					param_set_data(PAR_ID_SOP_CC , set_val);
					break;
				case 0x17:
					param_set_data(PAR_ID_SOP_DV , set_val);
					break;
				case 0x18:
					param_set_data(PAR_ID_SOP_DC , set_val);
					break;
				case 0x19: // 设置单体个数
					param_set_cell_num(set_val);
					break;
				case 0x1A: // 采样电阻值
					break;
				case 0x1B: // 设置温度个数					
					param_set_data(PAR_ID_CB_TEMP_NUM , set_val);
					break;
				case 0x1C: // 短路电压
				/*新增20241029*/
				 //  if (set_val <= 2500)
					param_set_data(PAR_ID_IDE_SC_CURR , set_val);
					afe_deinit_flag = 1;
					break;
				case 0x1D: // 短路延时
				/*新增20241029*/
				//   if (set_val <= 300)
					param_set_data(PAR_ID_IDE_SC_DLY , set_val);
					afe_deinit_flag = 1;
					break;
				case 0x1E: // 容量算法配置
					param_set_data(PAR_ID_SOC_CFG , set_val );
					break;
				case 0x1F: // 功能配置
					param_set_data(PAR_ID_FUNC_CFG , set_val );
					break;
				default:
					break;
			}
		}
	}
}

static void write_bms_calib_coeff(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t start_addr = 0;
	uint16_t end_addr = 0;
	uint16_t i = 0;
	const uint16_t *p_data = &comm_data.recv_reg_buf[2];
	uint16_t set_val = 0;
	
	start_addr = (comm_data.start_addr - 0x2100) / 2;
	end_addr = (comm_data.end_addr - 0x2100) / 2;
	
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		for( i = start_addr; i < end_addr; i ++ )
		{
			set_val = *p_data ++;
            if(i < 3)
            {
                switch(i)
                {
                    case 0x00: /* 零点校准 */
                        sample_calib_zero();
                        break;
                    case 0x01: /* 充电电流校准 */
                        sample_calib_chg(set_val);
                        break;
                    case 0x02: /* 放电电流校准 */
                        sample_calib_dsg(set_val);
                        break;
                    default:
                        break;
                }
            }
            if((i >= 3) && (i <= 26))
            {
                sample_calib_cvolt(i - 3 , set_val);
            }
			else
            {
                /* 校准温度 */
            }
		}
	}
}

static void write_bms_sys_time(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t idx_cnt = 0;
	uint16_t *p_buf = (uint16_t *)tx_buf;
	rtc_data_type rtc_time = {0};
	
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		rtc_time.year = comm_data.recv_reg_buf[2];
		rtc_time.month = comm_data.recv_reg_buf[3];
		rtc_time.day = comm_data.recv_reg_buf[4];
		rtc_time.hour = comm_data.recv_reg_buf[5];
		rtc_time.min = comm_data.recv_reg_buf[6];
		rtc_time.sec = comm_data.recv_reg_buf[7];
		
		If_rtc_set_time(rtc_time);
	}
	
	If_rtc_read_time(&rtc_time);
    p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.year);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.month);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.day);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.hour);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.min);
	p_buf[idx_cnt ++] = LIT_TO_BIG(rtc_time.sec);
	
	*tx_len = idx_cnt * 2;
}

static void write_bms_module_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		if(comm_data.start_addr == 0x2400)
		{
			param_set_data(PAR_ID_WIFI_ADDR , comm_data.recv_reg_buf[2]);
			param_set_data(PAR_ID_WIFI_ADDR + 1, comm_data.recv_reg_buf[3]);
			param_set_data(PAR_ID_WIFI_ADDR + 2, comm_data.recv_reg_buf[4]);
		}
		else if(comm_data.start_addr == 0x2406)
		{
			param_set_data(PAR_ID_MAC_ADDR , comm_data.recv_reg_buf[2]);
			param_set_data(PAR_ID_MAC_ADDR + 1, comm_data.recv_reg_buf[3]);
			param_set_data(PAR_ID_MAC_ADDR + 2, comm_data.recv_reg_buf[4]);
		}
		else if(comm_data.start_addr == 0x2414)
		{
			param_set_data(PAR_ID_IP_PORT , comm_data.recv_reg_buf[2]);
			param_set_data(PAR_ID_IP_PORT + 1, comm_data.recv_reg_buf[3]);
		}
        else if(comm_data.start_addr == 0x2418)
		{
			param_set_data(PAR_ID_SUB_CODE , comm_data.recv_reg_buf[2]);
			param_set_data(PAR_ID_SUB_CODE + 1, comm_data.recv_reg_buf[3]);
		}
		else if(comm_data.start_addr == 0x241C)
		{
			param_set_data(PAR_ID_DNS_CODE , comm_data.recv_reg_buf[2]);
			param_set_data(PAR_ID_DNS_CODE + 1, comm_data.recv_reg_buf[3]);
		}
		else if(comm_data.start_addr == 0x241E)
		{
			param_set_data(PAR_ID_WIFI_REP_EN , comm_data.recv_reg_buf[2]);
		}
		else if(comm_data.start_addr == 0x2420)
		{
			param_set_data(PAR_ID_WIFI_CYCLE , comm_data.recv_reg_buf[2]);
		}
		else
		{
			;
		}
	}
}

static void write_bms_debug_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
    uint16_t set_addr = 0;

	set_addr = (comm_data.start_addr - 0x2900) / 2;
	
	if(((comm_data.recv_reg_buf[0] & 0xff) == 0x4A)
	   &&(comm_data.recv_reg_buf[1] == 0x4244))
	{
		switch(set_addr)
        {
            case 0:
                var_set_data(VAR_ID_TOOL_MODE , comm_data.recv_reg_buf[2]);
				if(var_get_data(VAR_ID_TOOL_MODE) != TOOL_MODE_DEBUG)
				{
					var_set_data(VAR_ID_CTRL_BLC , 0);
					var_set_data(VAR_ID_OUT_CTRL , 0);
					var_set_data(VAR_ID_MOS_CTRL , 0);
					var_set_data(VAR_ID_LED_SW , 0);
				}
                break;
            case 1:
                var_set_data(VAR_ID_MOS_CTRL , comm_data.recv_reg_buf[2]);
                break;
            case 2:
                var_set_data(VAR_ID_OUT_CTRL , comm_data.recv_reg_buf[2]);
				if(comm_data.recv_reg_buf[2] & 0x08)
				{
					var_set_data(VAR_ID_OUT_CTRL , comm_data.recv_reg_buf[2] & 0xf7);
					if(TOOL_MODE_DEBUG == var_get_data(VAR_ID_TOOL_MODE))
					{
						ctrl_prp_sec_spro();
					}
				}
                break;
            case 3:
                var_set_data(VAR_ID_CTRL_BLC , comm_data.recv_reg_buf[2]);
                break;
            case 4:
                var_set_data(VAR_ID_CTRL_SLEEP , comm_data.recv_reg_buf[2]);
                break;
            case 5:
                var_set_data(VAR_ID_LED_SW , comm_data.recv_reg_buf[2]);
                break;
            case 6:
                if(comm_data.recv_reg_buf[2] == 0x55AA)
                {
                    param_valid_check(PARAM_RESET);
                    param_save_all();
                }
                break;
            case 7:
                if(comm_data.recv_reg_buf[2] == 0x5A5A)
                {
                    param_factory_setting();
                    param_save_all();
                    event_clr_all();
                }
                break;
            case 8:
                if(comm_data.recv_reg_buf[2] == 0x3A3A)
                {
                    event_clr_all();
                }
                break;
            case 9:
                if(comm_data.recv_reg_buf[2] == 0x4A4A)
                {
                   var_set_data(VAR_ID_USE_CMD ,USE_CMD_RESET);
                }
                break;
			case 10:
                var_set_data(VAR_ID_CALIB_CMD ,comm_data.recv_reg_buf[2]);
                break;
            default:
                break;
        }
	}
}

uint8_t parallel_com_read_slave_data(uint8_t *rx_buf , uint16_t rx_len)
{
    uint8_t slave_addr = 0;
    uint8_t i = 0;
    uint16_t data_idx = 0;
    uint8_t ret = FALSE;
    comm_data_type comm_recv_data = {0};
    
    if(BST_CMD_TRUE != check_frame_is_valid(rx_buf , rx_len , &comm_recv_data))
		return FALSE;
	
    if((comm_recv_data.addr >= CFG_PARALLEL_NUM) || (comm_recv_data.addr == 0))
        return FALSE;
	
	if(comm_recv_data.data_len == 0)
		return FALSE;
    
    slave_addr = comm_recv_data.addr - 1;
    
    switch(comm_recv_data.cmd)
    {
        case 0x45:
            slave_ol_data[slave_addr].ol_state = 1;
            slave_ol_data[slave_addr].recv_cnt = 1;
			slave_ol_data[slave_addr].send_cnt = 0;
			
            master_data_reg.slave_data[slave_addr].cell_num = comm_recv_data.recv_reg_buf[data_idx ++];
			for( i = 0;i < SLAVE_CELL_NUM; ++ i)
			{
				master_data_reg.slave_data[slave_addr].cell_volt_buf[i] = comm_recv_data.recv_reg_buf[data_idx ++];
			}
			master_data_reg.slave_data[slave_addr].max_cell_volt = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].min_cell_volt = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].batt_volt = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].curr_h16 = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].curr_l16 = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].max_temp = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].min_temp = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].full_cap = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].real_cap = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].cycle = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].soc = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].soh = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].prp_volt_status.prp_msg = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].prp_temp_status.prp_msg = comm_recv_data.recv_reg_buf[data_idx ++];
			master_data_reg.slave_data[slave_addr].fet_status = comm_recv_data.recv_reg_buf[data_idx ++];
            master_data_reg.slave_data[slave_addr].alarm_status = comm_recv_data.recv_reg_buf[data_idx ++];
            for( i = 0;i < 15; ++ i)
            {
                master_data_reg.slave_data[slave_addr].sn_code[i] = comm_recv_data.recv_reg_buf[data_idx ++];
            }
			master_data_reg.slave_data[slave_addr].sop_cc = comm_recv_data.recv_reg_buf[data_idx ++ ];
			master_data_reg.slave_data[slave_addr].sop_dc = comm_recv_data.recv_reg_buf[data_idx ++ ];
			master_data_reg.slave_data[slave_addr].ver_test = comm_recv_data.recv_reg_buf[data_idx ++ ];
			master_data_reg.slave_data[slave_addr].mos_temp = comm_recv_data.recv_reg_buf[data_idx ++ ];
			master_data_reg.slave_data[slave_addr].env_temp = comm_recv_data.recv_reg_buf[data_idx ++ ];
			master_data_reg.slave_data[slave_addr].version = comm_recv_data.recv_reg_buf[data_idx] & 0xff;
			master_data_reg.slave_data[slave_addr].temp_num = comm_recv_data.recv_reg_buf[data_idx] >> 8;
			data_idx ++ ;
			for( i = 0;i < SLAVE_TEMP_NUM; ++ i)
			{
				master_data_reg.slave_data[slave_addr].cell_temp_buf[i] = comm_recv_data.recv_reg_buf[data_idx ++];
			}
		//	master_data_reg.slave_data[slave_addr].std_cap = comm_recv_data.recv_reg_buf[data_idx];
            ret =  TRUE;
            break;
        default:
            break;
    }
    
    return ret;
}


uint8_t parallel_com_serialnet(uint8_t *rx_buf , uint16_t rx_len , serialnet_data_type *serianet_data)
{
    if((rx_buf[0] >= 0x01) && (rx_buf[0] <= CFG_PARALLEL_NUM) && 
		(((0x78 == rx_buf[1]) && ((rx_buf[2] << 8) + rx_buf[2]) >= 0x1800) || (0x79 == rx_buf[1])))
	{
        return TRUE;
	}
	else if((0xBB == rx_buf[0]) && (0xCC == rx_buf[rx_len-1]))
	{
		return TRUE;
	}
	else if((0xDD == rx_buf[0]) && (0x77 == rx_buf[rx_len-1]))
	{
		return TRUE;
	}
	else 
	{
		return FALSE;
	}
}

uint8_t parallel_com_analysis_recv(uint8_t *rx_buf , uint16_t rx_len, serialnet_data_type serianet_data)
{
	uint16_t calc_crc = 0;
    uint16_t recv_crc = 0;

	if((rx_buf[0] < 0x01) || (rx_buf[0] > CFG_PARALLEL_NUM))
        return FALSE;

    calc_crc = crc_chk(rx_buf , rx_len - 2);
    recv_crc = rx_buf[rx_len - 2] + (rx_buf[rx_len - 1] << 8);
    if(calc_crc != recv_crc)
        return FALSE;
	
	if((serianet_data.dev_addr == rx_buf[0]) && (rx_buf[1] == serianet_data.cmd))
		return TRUE;
    else
        return FALSE;
}

void com_report_total_msg(uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	uint32_t data = 0;
	int32_t v32_val = 0;
	int16_t v16_val = 0;
	
	tx_buf[tx_idx ++ ] = var_get_data(VAR_ID_SELF_ADDR);
	tx_buf[tx_idx ++ ] = 0x51;
	tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0xFF;
	tx_buf[tx_idx ++ ] = 0xFF;
    tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;
	
	/* 获取数据 */
	data = master_data_reg.avg_batt_volt;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	v32_val = master_data_reg.total_bus_curr * 0.1;
	v16_val = v32_val;
	tx_buf[tx_idx ++ ] = v16_val >> 8;
	tx_buf[tx_idx ++ ] = v16_val;
	data = master_data_reg.avg_soc;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_soh;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = var_get_data(VAR_ID_ENV_TEMP) + 2231;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_max_volt;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_min_volt;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_max_temp;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_min_temp;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.fet_status;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.total_real_cap * 0.1;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.total_full_cap * 0.1;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.parallel_num;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.com_err_state;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.avg_cycle;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.total_prp_msg.prp_word;
	tx_buf[tx_idx ++ ] = data >> 24;
	tx_buf[tx_idx ++ ] = data >> 16;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	
	data = master_data_reg.max_volt_sn;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.min_volt_sn;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.max_temp_sn;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = master_data_reg.min_temp_sn;
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
			
	data = param_get_data(PAR_ID_PCS_CAN_TYPE);
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
	data = param_get_data(PAR_ID_PCS_RS485_TYPE);
	tx_buf[tx_idx ++ ] = data >> 8;
	tx_buf[tx_idx ++ ] = data;
			
	data = tx_idx - 8;
	tx_buf[6] = data >> 8;
	tx_buf[7] = data & 0xff;
	calc_crc = crc_chk(tx_buf , tx_idx);
	tx_buf[tx_idx ++] = calc_crc & 0xff;
	tx_buf[tx_idx ++] = calc_crc >> 8;

	*tx_len = tx_idx;
}


/** ------------------------------------------------------------------------- *
  *                             Local function
 ** ------------------------------------------------------------------------- */
static uint8_t check_frame_is_valid(uint8_t *rx_buf , uint16_t rx_len , comm_data_type *comm_data)
{
    uint16_t calc_crc = 0;
    uint16_t recv_crc = 0;
    uint16_t i = 0;

    calc_crc = crc_chk(rx_buf , rx_len - 2);
    recv_crc = rx_buf[rx_len - 2] + (rx_buf[rx_len - 1] << 8);
    if(calc_crc != recv_crc)
        return BST_ERR_CRC;
   
    comm_data->addr = rx_buf[0];
    comm_data->cmd = rx_buf[1];
    comm_data->start_addr = (rx_buf[2] << 8) + rx_buf[3];
    comm_data->end_addr = (rx_buf[4] << 8) + rx_buf[5];
	comm_data->data_len = (rx_buf[6] << 8) + rx_buf[7];
    for( i = 0;(i < comm_data->data_len) && (i < RECV_REG_SIZE); ++ i)
    {
        comm_data->recv_reg_buf[i] = (rx_buf[8 + i * 2] << 8) + rx_buf[9 + i * 2];
    }
    
    return BST_CMD_TRUE;
}

static void com_master_auto_addr(uint8_t com_id , uint16_t cycle)
{
	uint8_t relay_addr = 0;
	uint8_t rx_buf[20] = {0};
	uint8_t rx_len = 0;
	if(RUN_STATE_AUTO_ADDR == com_auto_addr_data.run_state)
	{
		switch(com_auto_addr_data.auto_addr_state)
		{
			case AUTO_ADDR_START:
				com_auto_addr_data.send_dly_cnt += cycle;
				if(com_auto_addr_data.send_dly_cnt >= COM_TRY_DELAY)
				{
					com_auto_addr_data.send_dly_cnt = 0;
					com_master_send_set_addr(com_id ,0x00);
				}
				com_auto_addr_data.init_dly_cnt += cycle;
				if(com_auto_addr_data.init_dly_cnt >= COM_INIT_DELAY)
				{
					com_auto_addr_data.send_dly_cnt = 0;
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_RUNNING;
					com_auto_addr_data.now_set_addr = PARALLEL_MASTER_ADDR + 1;
					com_auto_addr_data.set_timeout_cnt = 0;
					com_auto_addr_data.init_dly_cnt = 0;
					com_master_send_set_addr(com_id ,com_auto_addr_data.now_set_addr);
					If_do_set_output(DO_AUTO_ADDR , DO_OUT_OFF);
				}
				break;
			case AUTO_ADDR_RUNNING:
				/* 发送标定 */
				com_auto_addr_data.send_dly_cnt += cycle;
				if(com_auto_addr_data.send_dly_cnt >= COM_TRY_DELAY)
				{
					com_auto_addr_data.send_dly_cnt = 0;
					com_master_send_set_addr(com_id , com_auto_addr_data.now_set_addr);
				}
				/* 接受到从机应答数据 */
				if(TRUE == If_com_recv_comp(com_id))
				{
					rx_len = If_com_get_recv_num(com_id);
					if(rx_len >= 20)
						rx_len = 20;
          			If_com_get_recv_buf(com_id , rx_buf , rx_len);
					if(TRUE == com_master_recv_slave_reply(rx_buf , rx_len , &relay_addr))
					{
						if(com_auto_addr_data.now_set_addr == relay_addr)
							com_auto_addr_data.now_set_addr ++ ;
						com_auto_addr_data.set_timeout_cnt = 0;
					}
				}
				/* 超时检测 */
				com_auto_addr_data.set_timeout_cnt += cycle;
				if(com_auto_addr_data.set_timeout_cnt >= COM_TIMEOUT)
				{
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_CMP;
					//com_auto_addr_data.run_state = RUN_STATE_NORMAL;
					If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
					com_master_send_set_addr(com_id , 0xff);
					com_auto_addr_data.send_dly_cnt = 0;
					com_auto_addr_data.set_timeout_cnt = 0;
					com_auto_addr_data.init_dly_cnt = 0;
				}
				break;
			case AUTO_ADDR_CMP:
				com_auto_addr_data.set_timeout_cnt += cycle;
				com_auto_addr_data.send_dly_cnt += cycle;
				if(com_auto_addr_data.set_timeout_cnt >= COM_OVER_DELAY)
				{
					com_auto_addr_data.run_state = RUN_STATE_NORMAL;
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
					com_auto_addr_data.send_dly_cnt = 0;
				}
				else if(com_auto_addr_data.send_dly_cnt >= COM_OVER_DELAY / 5)
				{
					com_auto_addr_data.send_dly_cnt = 0;
					com_master_send_set_addr(com_id , 0xff);
				}
				break;
			default:
				break;
		}
	}
}

static void com_slave_auto_addr(uint8_t com_id , uint16_t cycle)
{
	uint8_t set_addr = 0;
	uint8_t rx_buf[20] = {0};
	uint8_t rx_len = 0;
	if(RUN_STATE_AUTO_ADDR == com_auto_addr_data.run_state)
	{
		switch(com_auto_addr_data.auto_addr_state)
		{
			case AUTO_ADDR_START:
				If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
				var_set_data(VAR_ID_SELF_ADDR , 0x00);
				com_auto_addr_data.auto_addr_state = AUTO_ADDR_RUNNING;
				break;
			case AUTO_ADDR_RUNNING:
				/* 接受到主机设置命令 */
				if(TRUE == If_com_recv_comp(com_id))
				{
					rx_len = If_com_get_recv_num(com_id);
					if(rx_len >= 20)
						rx_len = 20;
          			If_com_get_recv_buf(com_id , rx_buf , rx_len);
					if(TRUE == com_slave_recv_master_set(rx_buf , rx_len , &set_addr))
					{
						if(set_addr == 0xff)
						{
							com_auto_addr_data.run_state = RUN_STATE_NORMAL;
							com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
						}
						else if(set_addr == 0x00)
						{
							// 初始化 不应答
							If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
						}
						else if((set_addr > 0) && (var_get_data(VAR_ID_SELF_ADDR) == 0x00))
						{
							if(If_di_read_in(DI_ADDR_IN) == DI_IN_OFF)
							{
								var_set_data(VAR_ID_SELF_ADDR , set_addr);
								param_set_data(PAR_ID_SELF_ADDR , set_addr);
								If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
								com_slave_send_reply(com_id , var_get_data(VAR_ID_SELF_ADDR));
							}
						}
						else if(set_addr == var_get_data(VAR_ID_SELF_ADDR))
						{
							com_slave_send_reply(com_id , var_get_data(VAR_ID_SELF_ADDR));
						}
						else if(set_addr == (var_get_data(VAR_ID_SELF_ADDR) + 1))
						{
							If_do_set_output(DO_AUTO_ADDR , DO_OUT_OFF);
						}
						com_auto_addr_data.set_timeout_cnt = 0;
					}
				}
				/* 超时检测 */
				com_auto_addr_data.set_timeout_cnt += cycle;
				if(com_auto_addr_data.set_timeout_cnt >= COM_TIMEOUT * 3)
				{
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_CMP;
					com_auto_addr_data.run_state = RUN_STATE_NORMAL;
					If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
					com_auto_addr_data.send_dly_cnt = 0;
					com_auto_addr_data.set_timeout_cnt = 0;
				}
				break;
			case AUTO_ADDR_CMP:
				com_auto_addr_data.send_dly_cnt += cycle;
				if(com_auto_addr_data.send_dly_cnt >= COM_OVER_DELAY)
				{
					com_auto_addr_data.run_state = RUN_STATE_NORMAL;
					com_auto_addr_data.auto_addr_state = AUTO_ADDR_START;
					If_do_set_output(DO_AUTO_ADDR , DO_OUT_ON);
					com_auto_addr_data.send_dly_cnt = 0;
				}
				break;
			default:
				break;
		}
	}
}

static void com_master_send_set_addr(uint8_t com_id , uint8_t set_addr)
{
	uint16_t tx_cnt = 0;
	uint16_t calc_crc = 0;
	uint8_t tx_buf[10] = {0};

	tx_buf[tx_cnt ++ ] = 0xDD;
	tx_buf[tx_cnt ++ ] = 0xAA;
	tx_buf[tx_cnt ++ ] = set_addr;
	calc_crc = modbus_calc_crc(tx_buf , tx_cnt);
	tx_buf[tx_cnt ++ ] = calc_crc & 0xff;
	tx_buf[tx_cnt ++ ] = calc_crc >> 8;

	If_com_send_str(com_id , tx_buf , tx_cnt);
}

static uint8_t com_master_recv_slave_reply(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *reply_addr)
{
	uint16_t calc_crc = 0;
	uint16_t recv_crc = 0;
	if(rx_len != 5)
		return FALSE;

	if((0xDD == rx_buf[0]) && (0xBB == rx_buf[1]))
	{
		calc_crc = modbus_calc_crc(rx_buf , rx_len - 2);
		recv_crc = (rx_buf[rx_len - 1] << 8) + rx_buf[rx_len - 2];
		if(calc_crc == recv_crc)
		{
			*reply_addr = rx_buf[2];
			return TRUE;
		}
	}

	return FALSE;
}

static uint8_t com_slave_recv_master_set(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *reply_addr)
{
	uint16_t calc_crc = 0;
	uint16_t recv_crc = 0;
	if(rx_len != 5)
		return FALSE;

	if((0xDD == rx_buf[0]) && (0xAA == rx_buf[1]))
	{
		calc_crc = modbus_calc_crc(rx_buf , rx_len - 2);
		recv_crc = (rx_buf[rx_len - 1] << 8) + rx_buf[rx_len - 2];
		if(calc_crc == recv_crc)
		{
			*reply_addr = rx_buf[2];
			return TRUE;
		}
	}

	return FALSE;
}

static void com_slave_send_reply(uint8_t com_id , uint8_t self_addr)
{
	uint16_t tx_cnt = 0;
	uint16_t calc_crc = 0;
	uint8_t tx_buf[10] = {0};

	tx_buf[tx_cnt ++ ] = 0xDD;
	tx_buf[tx_cnt ++ ] = 0xBB;
	tx_buf[tx_cnt ++ ] = self_addr;
	calc_crc = modbus_calc_crc(tx_buf , tx_cnt);
	tx_buf[tx_cnt ++ ] = calc_crc & 0xff;
	tx_buf[tx_cnt ++ ] = calc_crc >> 8;

	If_com_send_str(com_id , tx_buf , tx_cnt);
}

static uint8_t read_master_total_msg(const comm_data_type comm_data ,uint8_t *tx_buf , uint16_t *tx_len)
{
	uint16_t tx_idx = 0;
	uint16_t calc_crc = 0;
	uint32_t data = 0;
	uint16_t read_addr = 0;
	uint8_t i = 0;
	int32_t v32_val = 0;
	int16_t v16_val = 0;
	uint8_t cell_num = 0;
	
	tx_buf[tx_idx ++ ] = comm_data.addr;
	tx_buf[tx_idx ++ ] = comm_data.cmd;
	tx_buf[tx_idx ++ ] = comm_data.start_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.start_addr & 0xff;
	tx_buf[tx_idx ++ ] = comm_data.end_addr >> 8;
	tx_buf[tx_idx ++ ] = comm_data.end_addr & 0xff;
    tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;
	
	read_addr = comm_data.start_addr / 0x100;
	if(0 == read_addr)
	{
		if((PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR)) && 
			((PAL_MODE_SW_RS485 == parallel_get_mode()) || (RUN_STATE_AUTO_ADDR != com_auto_addr_data.run_state)))
		{
			/* 获取数据 */
			data = master_data_reg.avg_batt_volt;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			v32_val = master_data_reg.total_bus_curr * 0.1;
			v16_val = v32_val;
			tx_buf[tx_idx ++ ] = v16_val >> 8;
			tx_buf[tx_idx ++ ] = v16_val;
			data = master_data_reg.avg_soc;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.avg_soh;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_ENV_TEMP) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.avg_max_volt;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.avg_min_volt;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.max_temp_val;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.min_temp_val;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.fet_status;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.total_real_cap * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.total_full_cap * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.parallel_num;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.com_err_state;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.avg_cycle;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.total_prp_msg.prp_word;
			tx_buf[tx_idx ++ ] = data >> 24;
			tx_buf[tx_idx ++ ] = data >> 16;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = master_data_reg.max_volt_sn;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.min_volt_sn;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.max_temp_sn;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = master_data_reg.min_temp_sn;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = param_get_data(PAR_ID_PCS_CAN_TYPE);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_PCS_RS485_TYPE);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = tx_idx - 8;
			tx_buf[6] = data >> 8;
			tx_buf[7] = data & 0xff;
			calc_crc = crc_chk(tx_buf , tx_idx);
			tx_buf[tx_idx ++] = calc_crc & 0xff;
			tx_buf[tx_idx ++] = calc_crc >> 8;

			*tx_len = tx_idx;
			
			return TRUE;
		}
		else
		{
			/* 获取数据 */
			data = var_get_data(VAR_ID_BATT_VOLT);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			v16_val = var_get_data(VAR_ID_BUS_CURR) * 0.1 - 3000;
			tx_buf[tx_idx ++ ] = v16_val >> 8;
			tx_buf[tx_idx ++ ] = v16_val;
			data = var_get_data(VAR_ID_DISP_SOC) * 0.01;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_SOH);
			if(data > 100)
				data = 100;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_ENV_TEMP) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_MAX_CELL_VOLT);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_MIN_CELL_VOLT);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_MAX_TEMP_VAL) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_MIN_TEMP_VAL) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = 0;
			if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_CHG))
				data |= 0x02;
			if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_DSG))
				data |= 0x01;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_DISP_RCAP) * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_FULL_CAP) * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = 1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = 1 << (var_get_data(VAR_ID_SELF_ADDR) - 1);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_CYCLE);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = diag_get_all_prp();
			tx_buf[tx_idx ++ ] = data >> 24;
			tx_buf[tx_idx ++ ] = data >> 16;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = (var_get_data(VAR_ID_SELF_ADDR) << 8) + var_get_data(VAR_ID_MAX_CELL_SN);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = (var_get_data(VAR_ID_SELF_ADDR) << 8) + var_get_data(VAR_ID_MIN_CELL_SN);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = (var_get_data(VAR_ID_SELF_ADDR) << 8) + var_get_data(VAR_ID_MAX_TEMP_SN);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = (var_get_data(VAR_ID_SELF_ADDR) << 8) + var_get_data(VAR_ID_MIN_TEMP_SN);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = param_get_data(PAR_ID_PCS_CAN_TYPE);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_PCS_RS485_TYPE);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = tx_idx - 8;
			tx_buf[6] = data >> 8;
			tx_buf[7] = data & 0xff;
			calc_crc = crc_chk(tx_buf , tx_idx);
			tx_buf[tx_idx ++] = calc_crc & 0xff;
			tx_buf[tx_idx ++] = calc_crc >> 8;

			*tx_len = tx_idx;
			
			return TRUE;
		}
	}
	else
	{
		if(PARALLEL_MASTER_ADDR == var_get_data(VAR_ID_SELF_ADDR)) 
		{
			if(read_addr < CFG_PARALLEL_NUM)
			{
				read_addr = read_addr - 1;
				data = master_data_reg.slave_data[read_addr].batt_volt;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				v32_val = (master_data_reg.slave_data[read_addr].curr_h16 << 16) + master_data_reg.slave_data[read_addr].curr_l16;
				v16_val = v32_val * 0.1;
				tx_buf[tx_idx ++ ] = v16_val >> 8;
				tx_buf[tx_idx ++ ] = v16_val;
				data = master_data_reg.slave_data[read_addr].soc;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].soh;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].real_cap;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].full_cap;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].fet_status;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].prp_volt_status.prp_msg;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].prp_temp_status.prp_msg;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].mos_temp;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].env_temp;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				data = master_data_reg.slave_data[read_addr].temp_num;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				for( i = 0;i < SLAVE_TEMP_NUM; ++ i)
				{
					data = master_data_reg.slave_data[read_addr].cell_temp_buf[i];
					tx_buf[tx_idx ++ ] = data >> 8;
					tx_buf[tx_idx ++ ] = data;
				}
				data = master_data_reg.slave_data[read_addr].cell_num;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
				for( i = 0;i < SLAVE_CELL_NUM; ++ i)
				{
					data = master_data_reg.slave_data[read_addr].cell_volt_buf[i];
					tx_buf[tx_idx ++ ] = data >> 8;
					tx_buf[tx_idx ++ ] = data;
				}
				
				tx_buf[6] = tx_idx >> 8;
				tx_buf[7] = tx_idx & 0xff;
				calc_crc = crc_chk(tx_buf , tx_idx);
				tx_buf[tx_idx ++] = calc_crc & 0xff;
				tx_buf[tx_idx ++] = calc_crc >> 8;

				*tx_len = tx_idx;
				
				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
		else if(read_addr == var_get_data(VAR_ID_SELF_ADDR))
		{
			data = var_get_data(VAR_ID_BATT_VOLT);
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			v16_val = (var_get_data(VAR_ID_BUS_CURR)-30000)*0.1;
			tx_buf[tx_idx ++ ] = v16_val >> 8;
			tx_buf[tx_idx ++ ] = v16_val;
			data = var_get_data(VAR_ID_DISP_SOC) * 0.01;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_SOH);
			if(data > 100)
				data = 100;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_DISP_RCAP) * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = param_get_data(PAR_ID_FULL_CAP) * 0.1;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = 0;
			if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_CHG))
				data |= 0x02;
			if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_DSG))
				data |= 0x01;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = parallel_get_volt_prp_msg();
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = parallel_get_temp_prp_msg();
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_MOS_TEMP) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			data = var_get_data(VAR_ID_ENV_TEMP) + 2231;
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			
			data = param_get_data(PAR_ID_CB_TEMP_NUM);	
			if(data >= CFG_TEMP_NUM)
				data = CFG_TEMP_NUM;
			
			tx_buf[tx_idx ++ ] = data >> 8;
			tx_buf[tx_idx ++ ] = data;
			for( i = 0;i < SLAVE_TEMP_NUM; ++ i)
			{
				data = var_get_data(VAR_ID_CELL_TEMP01 + i) + 2231;
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
			}
			
			cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
			if(cell_num >= CELL_MAX_NUM)
				cell_num = CELL_MAX_NUM;
			tx_buf[tx_idx ++ ] = cell_num >> 8;
			tx_buf[tx_idx ++ ] = cell_num;
			for( i = 0;i < SLAVE_CELL_NUM; ++ i)
			{
				data = var_get_data(VAR_ID_CELL_VOLT01 + i);
				tx_buf[tx_idx ++ ] = data >> 8;
				tx_buf[tx_idx ++ ] = data;
			}
			
			tx_buf[6] = tx_idx >> 8;
			tx_buf[7] = tx_idx & 0xff;
			calc_crc = crc_chk(tx_buf , tx_idx);
			tx_buf[tx_idx ++] = calc_crc & 0xff;
			tx_buf[tx_idx ++] = calc_crc >> 8;

			*tx_len = tx_idx;
			
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
}

// 
static uint32_t pc_get_slave_prp(uint8_t addr)
{
	diag_prp_type prp_msg = {0};
	
	prp_msg.bit.cov = master_data_reg.slave_data[addr].prp_volt_status.name.cov;
	prp_msg.bit.cuv = master_data_reg.slave_data[addr].prp_volt_status.name.cuv;
	prp_msg.bit.bov = master_data_reg.slave_data[addr].prp_volt_status.name.bov;
	prp_msg.bit.buv = master_data_reg.slave_data[addr].prp_volt_status.name.buv;
	
	prp_msg.bit.occ = master_data_reg.slave_data[addr].prp_volt_status.name.occ;
	prp_msg.bit.ocd = master_data_reg.slave_data[addr].prp_volt_status.name.ocd;
	prp_msg.bit.ocd2 = master_data_reg.slave_data[addr].prp_volt_status.name.ocd2;
	
	prp_msg.bit.col = master_data_reg.slave_data[addr].prp_volt_status.name.col;
	prp_msg.bit.afe_err = master_data_reg.slave_data[addr].prp_volt_status.name.afe_err;
	prp_msg.bit.sc = master_data_reg.slave_data[addr].prp_volt_status.name.sc;
	
	prp_msg.bit.vdiff = master_data_reg.slave_data[addr].prp_volt_status.name.vdiff;
	
	prp_msg.bit.otc = master_data_reg.slave_data[addr].prp_temp_status.name.otc;
	prp_msg.bit.otd = master_data_reg.slave_data[addr].prp_temp_status.name.otd;
	prp_msg.bit.utc = master_data_reg.slave_data[addr].prp_temp_status.name.utc;
	prp_msg.bit.utd = master_data_reg.slave_data[addr].prp_temp_status.name.utd;
	
	prp_msg.bit.ote = master_data_reg.slave_data[addr].prp_temp_status.name.ote;
	prp_msg.bit.ute = master_data_reg.slave_data[addr].prp_temp_status.name.ute;
	prp_msg.bit.otm = master_data_reg.slave_data[addr].prp_temp_status.name.otm;
	prp_msg.bit.tol = master_data_reg.slave_data[addr].prp_temp_status.name.tol;
	
	prp_msg.bit.fcmos = master_data_reg.slave_data[addr].prp_temp_status.name.cmos_ft;
	prp_msg.bit.fdmos = master_data_reg.slave_data[addr].prp_temp_status.name.dmos_ft;
	prp_msg.bit.reverse = master_data_reg.slave_data[addr].prp_volt_status.name.reverse;
	prp_msg.bit.full_chg = master_data_reg.slave_data[addr].prp_volt_status.name.full_chg;
	
	return prp_msg.prp_word;
}

static uint32_t pc_get_slave_alarm(uint8_t addr)
{
	diag_alm_type alm_msg = {0};
	uint16_t read_alm = 0;
	
	read_alm = master_data_reg.slave_data[addr].alarm_status;
	
	if(read_alm & (1 << 0))
		alm_msg.bit.cov = 1;
	if(read_alm & (1 << 1))
		alm_msg.bit.cuv = 1;
	if(read_alm & (1 << 2))
		alm_msg.bit.ocd = 1;
	if(read_alm & (1 << 3))
		alm_msg.bit.occ = 1;
	if(read_alm & (1 << 4))
		alm_msg.bit.bov = 1;
	if(read_alm & (1 << 5))
		alm_msg.bit.buv = 1;
	if(read_alm & (1 << 6))
		alm_msg.bit.otc = 1;
	if(read_alm & (1 << 7))
		alm_msg.bit.utc = 1;
	if(read_alm & (1 << 8))
		alm_msg.bit.otd = 1;
	if(read_alm & (1 << 9))
		alm_msg.bit.utd = 1;
	if(read_alm & (1 << 10))
		alm_msg.bit.omtd = 1;
	if(read_alm & (1 << 11))
		alm_msg.bit.socl = 1;
	if(read_alm & (1 << 12))
		alm_msg.bit.oetd = 1;
	if(read_alm & (1 << 13))
		alm_msg.bit.uetd = 1;
	if(read_alm & (1 << 14))
		alm_msg.bit.vdiff = 1;
	if(read_alm & (1 << 15))
		alm_msg.bit.full_chg = 1;	
	
	return alm_msg.alm_word;
}
static uint16_t get_sys_mos_state(void)
{
	uint16_t state = 0;
    uint16_t mos_state = 0;
    
    mos_state = var_get_data(VAR_ID_MOS_STATE);
    
    if(mos_state & (1 << VAR_MOS_ST_DSG))
        state |= (1 << 0);
    if(mos_state & (1 << VAR_MOS_ST_CHG))
        state |= (1 << 1);
	if(If_do_get_out_state(DO_PCHG_CTRL) == DO_OUT_ON)
		state |= (1 << 2);
	if(If_do_get_out_state(DO_HOT_CTRL) == DO_OUT_ON)
		state |= (1 << 3);
	if(If_do_get_out_state(DO_FAN_CTRL) == DO_OUT_ON)
		state |= (1 << 4);
	if(If_do_get_out_state(DO_RLY_SOCL) == DO_OUT_ON)
		state |= (1 << 5);
	if(If_do_get_out_state(DO_RLY_FAULT) == DO_OUT_ON)
		state |= (1 << 6);
    if(If_do_get_out_state(DO_LIMIT_10A) == DO_OUT_ON)
		state |= (1 << 7);
	
	return state;
}

static uint16_t get_sys_sign_msg(void)
{
	uint16_t sign_state = 0;
    if(If_di_read_in(DI_CHG_SIGN) == DI_IN_ON)
        sign_state |= (1 << 0);
    if(If_di_read_in(DI_LOAD_SIGN) == DI_IN_ON)
        sign_state |= (1 << 1);
    if(If_di_read_in(DI_SW_SIGN) == DI_IN_ON)
        sign_state |= (1 << 2);
    
	return sign_state;
}

static uint16_t get_sys_salve_mos_state(uint8_t addr)
{
	uint8_t mos_state = 0;
	
	if(master_data_reg.slave_data[addr].fet_status & 0x01)
		mos_state |= (1 << 0);
	if(master_data_reg.slave_data[addr].fet_status & 0x02)
		mos_state |= (1 << 1);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 4)) // 限流10A
		mos_state |= (1 << 7);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 5)) // 故障干接点
		mos_state |= (1 << 6);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 6)) // SOC 干接点
		mos_state |= (1 << 5);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 7)) // 风扇MOS
		mos_state |= (1 << 4);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 8)) // 加热MOS
		mos_state |= (1 << 3);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 9)) // 预充MOS
		mos_state |= (1 << 2);
	
	return mos_state;
}

static uint16_t get_sys_slave_sign_msg(uint8_t addr)
{
	uint8_t sign_msg = 0;
		
	if(master_data_reg.slave_data[addr].fet_status & (1 << 10)) // 充电信号
		sign_msg |= (1 << 0);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 11)) // 负载信号
		sign_msg |= (1 << 1);
	if(master_data_reg.slave_data[addr].fet_status & (1 << 12)) // SW信号
		sign_msg |= (1 << 2);
	
	return sign_msg;	
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
